• xargs--冬天里的一丝暖意


    本文为博客园作者所写: 一寸HUI,个人博客地址:https://www.cnblogs.com/zsql/

    你有批量kill作业吗?有因为删除文件夹的内容太多而报错吗?-bash: /bin/rm: Argument list too long,查找出来的文件怎么直接删除呢?批量执行?并发执行?如果有这样的需求的话,就可以开始学习xargs命令了,本文主要的思路先提供一些简单的使用场景,然后再对xargs命令原理和使用进行阐述。

    一、简单使用场景

    1.1、使用场景

    • 传递参数,从而组合多个命令
    • 分隔数据,避免参数过长
    • 不支持管道的命令

    1.2、具体实例

    1.1、批量删除hive用户的所有进程

    ps aux | grep ^hive | grep -v grep | awk '{print $2}' | xargs kill -9

    1.2、分批次删除logs目录下2020年的所有文件,每批为10个

    cd  /logs && ls  | grep *2020* | xargs -n 10 rm -fr
    ls /logs | sed "s:^:`pwd`/:" | grep *2020* | xargs -n 10 rm -fr

    1.3、结合find命令进行处理文档,find命令可以查看:linux之find命令详解

    find . -name *.log -print0 | xargs rm -f #查找当前目录下的所有log文件,并删除
    find ./ -type f -name "*.txt" | xargs -i cp {}  /tmp/ #查找txt文件,并复制到/tmp目录下
    find ./ -type f  -name "*.log" | xargs -i -t  tar -zcvf {}.tar.gz {} #压缩日志文件

    1.4、批量下载

    cat urls.txt | xargs wget

    1.5、如果打通了ssh免密,假如有ip:192.168.88.130,192.168.88.131

    echo "192.168.88.130,192.168.88.131" | xargs -n 1 -P 2 -I __ip__ scp root@__ip__:/var/log/cron ./__ip__.cron #把这两个机器的cron日志复制到本地,取名为${ip}.cron

    二、原理和使用

    2.1、使用语法

    [root@lgh~]# xargs --help
    Usage: xargs [-0prtx] [--interactive] [--null] [-d|--delimiter=delim]
           [-E eof-str] [-e[eof-str]]  [--eof[=eof-str]]
           [-L max-lines] [-l[max-lines]] [--max-lines[=max-lines]]
           [-I replace-str] [-i[replace-str]] [--replace[=replace-str]]
           [-n max-args] [--max-args=max-args]
           [-s max-chars] [--max-chars=max-chars]
           [-P max-procs]  [--max-procs=max-procs] [--show-limits]
           [--verbose] [--exit] [--no-run-if-empty] [--arg-file=file]
           [--version] [--help] [command [initial-arguments]]

    2.2、原理说明

      在1.1中我们说了xargs使用的三个场景,一个是参数太长导致命令不能执行,就像rm一样,如果rm -rf /log/*,正如log目录下有很多很多个文件,这样就会出现/bin/rm: Argument list too long这样的错误,那为啥使用xargs就能删除了呢,因为xargs默认会把参数截取分批进行执行,这里使用了xargs的分割数据和传递参数原理,还有就是有些命令并不支持管道符,像ls命令,但是又想使用一行命令搞定,这样就可以使用xargs配合使用了。比如使用命令:echo text.txt  | xargs cat,这样可以把text.txt传递给cat命令作为参数,这样就可以查看该文件了,也就是说xargs完成了两个行为:处理管道传输过来的stdin;将处理后的传递到正确的位置上,还可以将stdin或者文件stdin分割成批,每个批中有很多分割片段,然后将这些片段按批交给xargs后面的命令进行处理,可能看到这里会有点懵逼,那简单点就是:xargs处理的优先级或顺序了:先分割,再分批,然后传递到参数位。

      举个例子:假如你有一个蛋糕,你要分给10个孩子去吃,首先第一步要进行切蛋糕(分割)那怎么切呢,切10块还是20块或者其他呢?所以这里就会存在切蛋糕方式的选择(分割方式),切好蛋糕后,小孩子都在不同的地方,你是选择每次送一块蛋糕呢,还是一次送两块呢(这就是分批,每批次传送多少个),送也要找到小孩的位置才能送到他手上吧,(这就是把分好批的文件或数据传递到命令指定的参数的位置),我想大家应该比较容易理解这个了,如果你还是没能理解,多看几遍:xargs处理的优先级或顺序了:先分割,再分批,然后传递到参数位,然后继续看下面的参数例子就懂了

    2.3、参数详解

    2.3.1、分割参数

    分割有三种方法:独立的xargs、xargs -d和xargs -0,后两者可以配合起来使用,既然都可以用来分割,那我们看看分割的方式:

    1、xargs分割:将接收到的stdout处理后传递到xargs后面的命令参数位,不写命令时默认的命令是echo,会对空格、tab、换行符,反斜线等进行分割

    [root@lgh test]# echo -e "a b c 
     dd 	 y"
    a b c
     dd      y
    [root@lgh test]# echo -e "a b c 
     dd 	 y" | xargs #默认会使用echo命令输出,这里的换行符和空格以及制表符都被作为分隔符用来分割了
    a b c dd y
    [root@lgh test]# echo -e "a b c 
     dd 	 y" | xargs echo
    a b c dd y

    将所有空格、制表符和分行符都替换为空格并压缩到一行上显示,这一整行将作为一个整体,这个整体的所有空格属性继承xargs处理前的符号属性(大概理解为,把这些分割好后用自己的所要的“段”替代,干掉别人的心腹(分隔符),换成自己的心腹)

    2、xargs -d分割:可以指定分段符,可以是单个符号、字母或数字。如指定字母o为分隔符:xargs -d"o"

    [root@lgh test]# echo -e "a bd
     cod 
     dod 	 y"
    a bd
     cod
     dod     y
    [root@lgh test]# echo -e "a bd
     cod 
     dod 	 y" |xargs -d 'o' #使用o进行分割,但是这样可能看的不是很清楚
    a bd
     c d
     d d     y

    这样看可能就清楚了:

    [root@lgh test]# echo -e "a bd
     cod 
     dod 	 y" |xargs -p -n 1  -d "o"  #-p参数交互参数,-n 1执行每批的个数,这些后面会说到
    /bin/echo a bd
     c ?... #打印第一批
    /bin/echo d
     d ?... #打印第二批
    /bin/echo d      y
     ?... #打印第三批
    /bin/echo ?...

    从上就可以看出来是指定的字符"o"进行分割了,使用xargs -d分割,会忽略空格、制表符、分行符等这些符号,会把这些当做内容保留下来,如上面的换行符都有保留下来,只有指定的"o"才是分割符

    3、xargs -0分割:可以处理接收的stdin中的null字符(),其实可以理解是xargs -d的一种特列,等价于xargs -d ""

    [root@mvxl2685 test]# echo -e "1 bbb uudddd"
    1 bbb
    uudddd
    [root@mvxl2685 test]# echo -e "1 bbb uudddd" | xargs -0
    1 bbb
    uu dddd

    [root@mvxl2685 test]# echo -e "1 bbb uudddd" | xargs -0 -p -n 1
    /bin/echo 1 bbb
    uu ?... #第一批
    /bin/echo dddd
    ?... #第二批
    /bin/echo ?...

    上面三种分割方式,使用最多的也就是默认的xargs了

    分割行为

    特殊符号处理方式

    分段方法

    配合分批选项

    分批方法

    xargs

    空格、制表符、分行符替换为空格,引号和反斜线删除。处理完后只有空格。如果空格、制表符和分行符使用引号包围则可以保留

    结果继承处理前的符号性质(文本符号还是标记意义符号)。

    -n

    以分段结果中的每个空格分段,进而分批。不管是文本还是标记意义的空格,只要是空格

    -L、-i

    以标记意义上的空格分段,进而分批

    不指定

    结果作为整体输出

    xargs -d

    xargs -d   不处理文本意义上的符号,所有标记意义上的符号替换为换行符 ,将-d指定的分割符替换为标记意义上的空格。

    结果中除了最后的空行和-d指定的分割符位的分段空格,其余全是文本意义上的符号

    按照-d指定的符号进行分段,每个段中可能包含文本意义上的空格、制表符、甚至是分行符。

    -n、-L、-i

    以标记意义上的符号(即最后的空行和-d指定分隔符位的空格)分段,进而分批。分段结果中保留所有段中的符号,包括制表符和分行符。

    不指定

    结果作为整体输出

    xargs -0

    不处理文本意义上的符号,将非的标记意义上的符号替换为 ,将替换为空格。

    结果中除了最后空行和位的空格,其余都是文本意义上的符号

    以替换位的空格分段,每个段中可能包含文本意义上的空格、制表符、甚至是分行符。

    如果没检测到,则只有一个不可分割的段。

    -n、-L、-i

    检测到时,以标记意义上的符号(即最后的空行和位的空格)分段,进而分批。分段结果中保留所有段中的符号,包括制表符和分行符。

    未检测到时,整个结果作为不可分割整体,使用分批选项是无意义的

    不指定

    结果作为整体输出

    2.3.2、分批参数

    上面一节中我们知道怎么切蛋糕了(分割),接下来我们就怎么把这些分割好的内容组装成批次。可以使用-n和-L两个参数,那具体他们有什么区别呢?请继续往下看:
    1、使用-n分批

    假如有文件夹test:

    [root@lgh test]# ll
    total 0
    -rw-r--r-- 1 root root 0 Dec  4 14:33 a
    -rw-r--r-- 1 root root 0 Dec  4 14:33 b
    -rw-r--r-- 1 root root 0 Dec  4 14:33 c
    -rw-r--r-- 1 root root 0 Dec  4 14:33 dd
    -rw-r--r-- 1 root root 0 Dec  4 14:33 gg
    -rw-r--r-- 1 root root 0 Dec  4 14:33 u t.txt #这是个特殊文件,有空格的文件名
    -rw-r--r-- 1 root root 0 Dec  4 14:33 uu

    接下我们使用-n分批会有怎样的效果呢?

    [root@lgh test]# ls | xargs -n 2 #每两个作为一个批次
    a b
    c dd
    gg u  #这里把u t.txt文件拆到两个批次中了,这并不是我们想要的
    t.txt uu

    xargs -n分两种情况:和独立的xargs一起使用,这时按照每个空格分段划批;和xargs -d或xargs -0一起使用,这时按段分批,即不以空格、制表符和分行符分段划批

    2、使用-L分批

    [root@lgh test]# ls | xargs -L 2 #每两个作为一个批次
    a b
    c dd
    gg u t.txt #这里就没有拆分u t.txt文件
    uu

    -n选项类似,唯一的区别是-L永远是按段划批,而-n在和独立的xargs一起使用时是按空格分段划批的

    2.3.3、位置传递参数

    xargs -i和xargs -I选项在逻辑上用于接收传递的分批结果,如果不使用这两个选项,则默认是将分割后处理后的结果整体传递到命令的最尾部,有时候可能需要到多个位置,或者不是最后一个位置,例如cp命令一样,所以这两个参数很重要。

    使用xargs -i时以大括号{}作为替换符号,传递的时候看到{}就将被结果替换。可以将{}放在任意需要传递的参数位上,如果多个地方使用{}就实现了多个传递

    假如有目录test:

    [root@lgh test]# ll
    total 0
    -rw-r--r-- 1 root root 0 Dec  4 14:51 10.log
    -rw-r--r-- 1 root root 0 Dec  4 14:51 1.log
    -rw-r--r-- 1 root root 0 Dec  4 14:51 2.log
    -rw-r--r-- 1 root root 0 Dec  4 14:51 3.log
    -rw-r--r-- 1 root root 0 Dec  4 14:51 4.log
    -rw-r--r-- 1 root root 0 Dec  4 14:51 5.log
    -rw-r--r-- 1 root root 0 Dec  4 14:51 6.log
    -rw-r--r-- 1 root root 0 Dec  4 14:51 7.log
    -rw-r--r-- 1 root root 0 Dec  4 14:51 8.log
    -rw-r--r-- 1 root root 0 Dec  4 14:51 9.log

    现在需要把它们全部备份起来,编程*.log.bak文件

    [root@lgh test]# ls | xargs  -i mv  {} {}.bak #这里使用-i接收,然后使用{}指定位置
    [root@lgh test]# ll
    total 0
    -rw-r--r-- 1 root root 0 Dec  4 14:51 10.log.bak
    -rw-r--r-- 1 root root 0 Dec  4 14:51 1.log.bak
    -rw-r--r-- 1 root root 0 Dec  4 14:51 2.log.bak
    -rw-r--r-- 1 root root 0 Dec  4 14:51 3.log.bak
    -rw-r--r-- 1 root root 0 Dec  4 14:51 4.log.bak
    -rw-r--r-- 1 root root 0 Dec  4 14:51 5.log.bak
    -rw-r--r-- 1 root root 0 Dec  4 14:51 6.log.bak
    -rw-r--r-- 1 root root 0 Dec  4 14:51 7.log.bak
    -rw-r--r-- 1 root root 0 Dec  4 14:51 8.log.bak
    -rw-r--r-- 1 root root 0 Dec  4 14:51 9.log.bak

    -I则可以指定其他的符号、字母、数字作为替换符号,例如xargs -I

    [root@lgh test]# ls | xargs  -I bb mv  bb bb.I #这里使用-I参数指定bb为接收替代符
    [root@lgh test]# ll
    total 0
    -rw-r--r-- 1 root root 0 Dec  4 14:51 10.log.bak.I
    -rw-r--r-- 1 root root 0 Dec  4 14:51 1.log.bak.I
    -rw-r--r-- 1 root root 0 Dec  4 14:51 2.log.bak.I
    -rw-r--r-- 1 root root 0 Dec  4 14:51 3.log.bak.I
    -rw-r--r-- 1 root root 0 Dec  4 14:51 4.log.bak.I
    -rw-r--r-- 1 root root 0 Dec  4 14:51 5.log.bak.I
    -rw-r--r-- 1 root root 0 Dec  4 14:51 6.log.bak.I
    -rw-r--r-- 1 root root 0 Dec  4 14:51 7.log.bak.I
    -rw-r--r-- 1 root root 0 Dec  4 14:51 8.log.bak.I
    -rw-r--r-- 1 root root 0 Dec  4 14:51 9.log.bak.I

    注意:-i、-L、-n这三个参数在一起,都会被最后一个覆盖,也就是一起使用的时候,只有最后一个生效

    2.3.4、其他参数

    上面已经把最重要的一些参数介绍完了,我们看看其他参数

    1、-p和-t:交互参数,可以用于前期不确定执行过程,用来测试自己写的代码是否符合最终的执行命令

    -p是询问是否打印,y键表示打印,回车表示不打印

    [root@lgh test]# ls | xargs -n 3 -p
    /bin/echo 10.log.bak.I 1.log.bak.I 2.log.bak.I ?...y #询问打印,按下y
    /bin/echo 3.log.bak.I 4.log.bak.I 5.log.bak.I ?...10.log.bak.I 1.log.bak.I 2.log.bak.I #打印出上一次询问的值,然后继续询问下一个批次是否打印,按下回车,不打印输出
    
    /bin/echo 6.log.bak.I 7.log.bak.I 8.log.bak.I ?...
    /bin/echo 9.log.bak.I ?...

    -t是先把执行的语句打印出来,然后把要输出的内容打印出来

    [root@lgh test]# ls | xargs -n 3 -t
    /bin/echo 10.log.bak.I 1.log.bak.I 2.log.bak.I #打印执行的语句
    10.log.bak.I 1.log.bak.I 2.log.bak.I #打印执行语句的结果
    /bin/echo 3.log.bak.I 4.log.bak.I 5.log.bak.I
    3.log.bak.I 4.log.bak.I 5.log.bak.I
    /bin/echo 6.log.bak.I 7.log.bak.I 8.log.bak.I
    6.log.bak.I 7.log.bak.I 8.log.bak.I
    /bin/echo 9.log.bak.I
    9.log.bak.I

    2、-P:批量执行参数(并发,一起执行)哈哈,反正就是同时执行

    在执行某一个命令的时候,后面很多参数的时候,例如:rm log/* 会对log下的每一个目录进行依次删除,就算使用xargs的分批执行,还是一个一个执行的,并不会提高效率,接下来该-P参数出场了

    "-P N"选项可以指定并行处理的进程数量为N。不指定"-P"时,默认为1个处理进程,也就是串行执行。指定为0时,将尽可能多地开启进程数量

    [root@lgh ~]# time echo {1..3} | xargs -n 1 sleep #不使用-P,并每个批次为1,总共的执行时间为6秒
    
    real    0m6.005s
    user    0m0.001s
    sys     0m0.001s
    [root@lgh ~]# time echo {1..3} | xargs -n 3 sleep #不使用-P,每个批次为3,总共执行时间为6秒,分批不能提高速度
    
    real    0m6.003s
    user    0m0.000s
    sys     0m0.002s
    [root@lgh ~]# time echo {1..3} | xargs -n 3 -P 3 sleep #使用-P,每个批次为3,说明只有一个批次,所以一个线程需要一次执行所有的命令,所以还是6秒,没有达到并发的效果
    
    real    0m6.003s
    user    0m0.001s
    sys     0m0.000s
    [root@lgh ~]# time echo {1..3} | xargs -n 1 -P 3 sleep #使用-P,每个批次为1,所以可以同时执行命令,执行时间为3秒
    
    real    0m3.003s
    user    0m0.001s
    sys     0m0.001s

    很多时候,执行大量命令的时候可以使用-P提高效率

    2.4、总结

    xargs命令很强大,你值得拥有!!!如果使用的得当不仅可以提高逼格,还可以提高效率,能够做一些原本命令不能做到的事情,好好学号xargs何乐而不为呢?

    xargs的总结:分割(xargs,xargs -d,xargs -0)、分批(-n,-L)、传递到指定位置(-i,-I)

    参考:

    https://www.cnblogs.com/f-ck-need-u/p/5925923.html#auto_id_9

     https://blog.chenyuanwai.com/xargs/

    https://blog.csdn.net/lilongsy/article/details/77535687

  • 相关阅读:
    Study Plan The Twelfth Day
    Study Plan The Fifteenth Day
    Study Plan The Seventeenth Day
    Study Plan The Tenth Day
    Study Plan The Eighth Day
    Study Plan The Eleventh Day
    Study Plan The Sixteenth Day
    Study Plan The Thirteenth Day
    Study Plan The Fourteenth Day
    Study Plan The Ninth Day
  • 原文地址:https://www.cnblogs.com/zsql/p/14085003.html
Copyright © 2020-2023  润新知