Linux - 在后台同时执行 shell 个脚本并知道何时完成
Linux - Execute shell scripts simultaneously on the background and know when its done
我正在使用 rsync
将文件从一台服务器传输到另一台服务器(均归我所有),我唯一的问题是这些文件超过 50GB,我需要传输大量文件(其中超过 200 个)。
现在我可以打开多个选项卡和 运行 rsync
或在脚本末尾添加“&”以在后台执行它。
所以我的问题是,如何在后台执行此命令,当它完成传输后,我希望在执行脚本的终端 window 上显示一条消息。
(rsync -av -progress [FOLDER_NAME] [DISTINATION]:[PATH] &) && echo 'Finished'
我知道那是完全错误的,但我需要在后台使用 & 来 运行 它,并在 rsync 完成后使用 && 来 运行 回显。
您可以为此使用 gnu screen,screen 可以 monitor 输出静音和 activity。额外的好处 - 您可以关闭终端并稍后重新连接到屏幕 - 如果您 运行 可以在服务器上进行屏幕就更好了 - 然后您可以关闭或重新启动您的机器并且屏幕中的进程仍在执行。
除了基于 screen
的解决方案,您还可以使用 xargs
工具。
echo '/srcpath1 host1 /dstpath1
/srcpath2 host2 /dstpath2
/srcpath3 host3 /dstpath3'| \
xargs -P 5 --max-lines 1 bash -e 'rsync -av -progress :'
xargs
读取标准输入的输入,并为每个单词或行执行一个命令。这次,行。
它的优势在于:它可以并行执行 child 进程!在此配置中,xargs 通过始终使用 5 个并行 child 进程来执行此操作。这个数字可以是1,甚至可以是无穷大。
xargs 将退出,如果它的所有 child 都准备就绪,并且可以很好地处理每个 ctrl/c、child 处理等,并且可以容忍问题。
而不是 echo
,xargs
的输入可以来自文件,甚至也可以来自管道中的先前命令。或者来自 for
或 while
循环。
好吧,为了回答你的具体问题,你的调用:
(rsync ... &) && echo 'Finished'
创建一个子外壳 - ( ... )
位 - 其中 rsync
在后台 运行,这意味着子外壳将在启动后立即退出 rsync
,而不是在 rsync
完成之后。 && echo ...
部分然后注意到子 shell 已成功退出并执行其操作,这不是您想要的,因为 rsync
很可能仍然是 运行ning.
要完成你想要的,你需要这样做:
(rsync ... && echo 'Finished') &
这会将子 shell 本身置于后台,子 shell 将 运行 rsync
然后 echo
。如果您需要在稍后的脚本中等待该子 shell 完成,只需在适当的位置插入 wait
。
你也可以这样构造它:
rsync ... &
# other stuff to do while rsync runs
wait
echo 'Finished'
哪个是"better"真的只是一个偏好问题。只有在 rsync
不报告错误退出代码时 &&
才会 运行 echo
有一个细微差别 - 但将 &&
替换为 [=26] =] 会使这两个模式更等价。第二种方法使 echo
与脚本的其他输出同步,因此它不会出现在其他输出的中间,因此从这方面来看它可能稍微更可取,但捕获 [= 的退出条件14=] 如果有必要的话会更复杂...
我正在使用 rsync
将文件从一台服务器传输到另一台服务器(均归我所有),我唯一的问题是这些文件超过 50GB,我需要传输大量文件(其中超过 200 个)。
现在我可以打开多个选项卡和 运行 rsync
或在脚本末尾添加“&”以在后台执行它。
所以我的问题是,如何在后台执行此命令,当它完成传输后,我希望在执行脚本的终端 window 上显示一条消息。
(rsync -av -progress [FOLDER_NAME] [DISTINATION]:[PATH] &) && echo 'Finished'
我知道那是完全错误的,但我需要在后台使用 & 来 运行 它,并在 rsync 完成后使用 && 来 运行 回显。
您可以为此使用 gnu screen,screen 可以 monitor 输出静音和 activity。额外的好处 - 您可以关闭终端并稍后重新连接到屏幕 - 如果您 运行 可以在服务器上进行屏幕就更好了 - 然后您可以关闭或重新启动您的机器并且屏幕中的进程仍在执行。
除了基于 screen
的解决方案,您还可以使用 xargs
工具。
echo '/srcpath1 host1 /dstpath1
/srcpath2 host2 /dstpath2
/srcpath3 host3 /dstpath3'| \
xargs -P 5 --max-lines 1 bash -e 'rsync -av -progress :'
xargs
读取标准输入的输入,并为每个单词或行执行一个命令。这次,行。
它的优势在于:它可以并行执行 child 进程!在此配置中,xargs 通过始终使用 5 个并行 child 进程来执行此操作。这个数字可以是1,甚至可以是无穷大。
xargs 将退出,如果它的所有 child 都准备就绪,并且可以很好地处理每个 ctrl/c、child 处理等,并且可以容忍问题。
而不是 echo
,xargs
的输入可以来自文件,甚至也可以来自管道中的先前命令。或者来自 for
或 while
循环。
好吧,为了回答你的具体问题,你的调用:
(rsync ... &) && echo 'Finished'
创建一个子外壳 - ( ... )
位 - 其中 rsync
在后台 运行,这意味着子外壳将在启动后立即退出 rsync
,而不是在 rsync
完成之后。 && echo ...
部分然后注意到子 shell 已成功退出并执行其操作,这不是您想要的,因为 rsync
很可能仍然是 运行ning.
要完成你想要的,你需要这样做:
(rsync ... && echo 'Finished') &
这会将子 shell 本身置于后台,子 shell 将 运行 rsync
然后 echo
。如果您需要在稍后的脚本中等待该子 shell 完成,只需在适当的位置插入 wait
。
你也可以这样构造它:
rsync ... &
# other stuff to do while rsync runs
wait
echo 'Finished'
哪个是"better"真的只是一个偏好问题。只有在 rsync
不报告错误退出代码时 &&
才会 运行 echo
有一个细微差别 - 但将 &&
替换为 [=26] =] 会使这两个模式更等价。第二种方法使 echo
与脚本的其他输出同步,因此它不会出现在其他输出的中间,因此从这方面来看它可能稍微更可取,但捕获 [= 的退出条件14=] 如果有必要的话会更复杂...