我编写了一个小型 bash 脚本,用于抓取 URL 的 XML 站点地图。它使用 xargs 并行检索 5 个 URL。
现在我想在所有的URL都被抓取之后发送一封电子邮件,所以必须等到xargs的所有子进程都完成后才能发送邮件。
我已尝试在 xargs 后使用管道:
#!/bin/bash
wget --quiet --no-cache -O- http://some.url/test.xml | egrep -o "http://some.url[^<]+" | xargs -P 5 -r -n 1 wget --spider | mail...
与wait
#!/bin/bash
wget --quiet --no-cache -O- http://some.url/test.xml | egrep -o "http://some.url[^<]+" | xargs -P 5 -r -n 1 wget --spider
wait
mail ...
这两种方法都不起作用,脚本执行后会立即发送电子邮件。我该如何实现这一点?不幸的是,parallel
我的服务器(托管主机)上没有该程序。
答案1
xargs
不要使用,而是wget
在后台单独生成每个进程,并将后台进程的 PID 收集到列表中。此外,确保将后台进程的输出写入文件。
一旦所有后台进程都已启动,请执行全部列表中的 PID 和wait
每个 PID——已经退出的 PID 将不会阻塞wait
。现在,希望已经成功等待了所有后台进程,剩下要做的就是将每个后台进程的输出连接到单个文件,然后将其发送到需要输出的任何地方。
类似于这样的(当然,回声是多余的,仅用于演示目的):
#!/bin/bash
mail=$(tempfile)
pids=()
outputs=()
trap "rm -f ${outputs[@]}" EXIT
trap "rm -f $mail" EXIT
for url in $(wget --quiet --no-cache -O- http://some.url/test.xml |\
egrep -o "http://some.url[^<]+") ; do
output=$(tempfile)
wget --spider > $output 2>&1 &
pids+=($!)
outputs+=($output)
echo "Spawned wget and got PID ${pids[-1]}."
done
for pid in ${pids[@]} ; do
echo "Waiting for PID $pid."
wait $pid
done
# Concatenate outputs from individual processes into a single file.
for output in ${outputs[@]} ; do cat $output >> $mail ; done
# Mail that file.
< $mail mail -s "All outputs" [email protected]
# end of file.