从bash脚本启动进程失败
我有一个中央服务器,我定期启动一个脚本(从cron)来检查远程服务器。该检查是连续执行的,所以首先,一个服务器然后另一个......。从bash脚本启动进程失败
这个脚本(从中央服务器)启动另一个脚本(让我们称之为它update.sh)在远程机器上,并且该脚本(在远程计算机上)正在做这样的事情:
processID=`pgrep "processName"`
kill $processID
startProcess.sh
该过程被杀死,然后在脚本startProcess.sh开始是这样的:
pidof "processName"
if [ ! $? -eq 0 ]; then
nohup "processName" "processArgs" >> "processLog" &
pidof "processName"
if [! $? -eq 0]; then
echo "Error: failed to start process"
...
,它开始是在NFS挂载从中央服务器的update.sh,startprocess.sh和过程的实际二进制。
现在会发生什么有时,是我尝试在startprocess.sh中启动的进程未启动,并且出现错误。奇怪的部分是它是随机的,有时在一台机器上的过程开始,并且在同一台机器上的另一次不启动。我正在检查大约300台服务器,错误总是随机的。还有一件事,远程服务器位于3个不同的地理位置(美国2个,欧洲1个),中央服务器位于欧洲。从我目前发现的情况来看,美国的服务器比在欧洲的服务器有更多的错误。
首先,我认为错误必须与kill有关,所以我在kill和startprocess.sh之间添加了一个睡眠,但没有任何区别。
此外,似乎从startprocess.sh开始的进程根本没有启动,或者它启动时发生了什么,因为日志文件中没有输出,并且应该是是日志文件。
所以,我在这里寻求帮助
有谁有这样那样的问题,或知道什么可能是错误的?
感谢所有帮助
(很抱歉,但我原来的答复是相当错误的......这是修正)
使用$?
获得在startProcess.sh
线索后台进程的退出状态到错误的结果。男人bash状态:
Special Parameters
? Expands to the status of the most recently executed foreground
pipeline.
正如你在评论中提及获得后台进程的退出状态使用内置在wait
的正确方法,但这种bash必须处理SIGCHLD信号。
我给这个小测试环境,以展示它如何工作的:
这里是一个脚本loop.sh
作为后台进程运行:
#!/bin/bash
[ "$1" == -x ] && exit 1;
cnt=${1:-500}
while ((++c<=cnt)); do echo "SLEEPING [$$]: $c/$cnt"; sleep 5; done
如果arg是-x
然后退出退出状态1模拟错误。如果arg是num,则等待num * 5秒打印SLEEPING [<PID>] <counter>/<max_counter>
到标准输出。
第二个是启动脚本。它在后台启动3个loop.sh
脚本并打印其退出状态:
#!/bin/bash
handle_chld() {
local tmp=()
for i in ${!pids[@]}; do
if [ ! -d /proc/${pids[i]} ]; then
wait ${pids[i]}
echo "Stopped ${pids[i]}; exit code: $?"
unset pids[i]
fi
done
}
set -o monitor
trap "handle_chld" CHLD
# Start background processes
./loop.sh 3 &
pids+=($!)
./loop.sh 2 &
pids+=($!)
./loop.sh -x &
pids+=($!)
# Wait until all background processes are stopped
while [ ${#pids[@]} -gt 0 ]; do echo "WAITING FOR: ${pids[@]}"; sleep 2; done
echo STOPPED
的handle_chld功能将处理SIGCHLD信号。设置选项monitor
允许非交互式脚本接收SIGCHLD。然后陷阱被设置为SIGCHLD信号。
然后启动后台进程。所有的PID都记录在pids
阵列中。如果接收到SIGCHLD,则会在/ proc /目录中检查哪个子进程已停止(缺少的进程)(它也可以使用内置的kill -0 <PID>
bash进行检查)。等待后台进程的退出状态存储在着名的$?
伪变量中。
主脚本等待所有的pid停止(否则无法获得其子节点的退出状态),并停止其自身。
一个例子输出:
WAITING FOR: 13102 13103 13104
SLEEPING [13103]: 1/2
SLEEPING [13102]: 1/3
Stopped 13104; exit code: 1
WAITING FOR: 13102 13103
WAITING FOR: 13102 13103
SLEEPING [13103]: 2/2
SLEEPING [13102]: 2/3
WAITING FOR: 13102 13103
WAITING FOR: 13102 13103
SLEEPING [13102]: 3/3
Stopped 13103; exit code: 0
WAITING FOR: 13102
WAITING FOR: 13102
WAITING FOR: 13102
Stopped 13102; exit code: 0
STOPPED
出射码被正确地报告可以看出。
我希望这可以帮助一下!
我怀疑你可能在[Server Fault](http://serverfault.com/)上比在Stack Overflow上做得更好。您的症状听起来像跨大西洋的连接可能较慢,NFS操作更可能超时。如果软件是自动安装的,则可能是相关的目录在命令失败时不可用,但在命令成功时可用;我以前见过类似的问题。还有“如果你有足够的机器,一些总是失败的”综合症。与成千上万台机器一起工作,而不是数百台家用机器。 – 2014-10-20 22:29:48