我使用 xargs 工具来管理串行和并行运行多个命令,即同时运行 4 个任务,同时使用 -a 命令行选项从要执行的命令列表中读取,即
xargs -t -P 4 -L 1 -I '%' -a files.txt runSh.sh
其中 files.txt 包含配置列表,该列表作为命令行参数传递给 runSh.sh。
我的问题是,我可以在 xargs 运行时将行追加到 files.txt 中,并且 xargs 会将这些附加命令添加到其执行队列中,还是在执行时只读取一次 files.txt 输入文件?
谢谢
答案1
您可以运行它来strace
查看发生了什么:
$ seq 10 > files.txt
$ strace -tt -e read xargs -t -P 4 -n1 -d'\n' -a files.txt sleep
[...]
18:19:32.907311 read(3, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n", 512) = 21
sleep 1
18:19:32.908129 read(4, "", 4) = 0
sleep 2
18:19:32.908830 read(4, "", 4) = 0
sleep 3
18:19:32.909406 read(4, "", 4) = 0
sleep 4
18:19:32.909977 read(4, "", 4) = 0
18:19:33.912774 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=453051, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
sleep 5
18:19:33.914702 read(4, "", 4) = 0
18:19:34.910440 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=453052, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
sleep 6
18:19:34.911021 read(4, "", 4) = 0
18:19:35.911315 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=453053, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
sleep 7
18:19:35.912257 read(4, "", 4) = 0
18:19:36.912158 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=453054, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
sleep 8
18:19:36.912623 read(4, "", 4) = 0
18:19:38.916348 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=453176, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
sleep 9
18:19:38.917196 read(4, "", 4) = 0
18:19:40.913135 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=453177, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
sleep 10
18:19:40.914137 read(4, "", 4) = 0
18:19:40.914808 read(3, "", 512) = 0
18:19:42.914324 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=453178, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
18:19:44.914685 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=453179, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
18:19:47.919202 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=453272, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
18:19:50.916332 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=453273, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
18:19:50.917068 +++ exited with 0 +++
正如您所看到的,它最初读取最多 512 字节的数据,在我的例子中足以读取文件的全部内容(21 字节),然后启动 4 个进程。
一旦第一个命令sleep
返回,它就会开始下一个命令。
当它启动了最初读取的所有命令时,它read()
再次来自该文件描述符 3,它不返回任何内容,这意味着文件结尾,之后就不再读取了。
因此,xargs
(这里的 GNU xargs
,如同-P
,都是 GNU 特有的)将仅读取在启动最后一个命令-d
之前已附加的附加数据。xargs
如果您希望始终能够添加更多数据并确保xargs
读取它,您可以将其更改为:
xargs -t -P 4 -n1 -d'\n' -a <(tail -fn +1 files.txt) sleep
(假设 shell 支持进程替换,例如 ksh、zsh 或 bash)
这次,xargs
将从永远不会结束的管道中读取(永远不会在其上看到文件结尾)。tail -f
,因此xargs
将永远等待来自该文件的更多数据。
答案2
我刚刚做了一个实验。我制作了一个如下所示的小 shell 脚本
echo $1
sleep 1m
我有一个如下所示的配置文件
one
two
three
four
然后我开始命令
xargs -t -P 4 -L 1 -a input_lines.txt ./run2.sh
一旦开始运行,我修改了 input_lines.txt 文件,使其看起来像
one
two
three
four
five
执行完成,只输出
./run2.sh one
./run2.sh two
one
./run2.sh three
two
./run2.sh four
three
four
综上所述,这表明 xargs 在运行时读取 -a 命令行指定的输入文件并使用该文件 - 您无法在执行期间修改该文件,并且无法在执行中反映修改后的输入。
三四