从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开始的进程根本没有启动,或者它启动时发生了什么,因为日志文件中没有输出,并且应该是是日志文件。

所以,我在这里寻求帮助

有谁有这样那样的问题,或知道什么可能是错误的?

感谢所有帮助

+1

我怀疑你可能在[Server Fault](http://serverfault.com/)上比在Stack Overflow上做得更好。您的症状听起来像跨大西洋的连接可能较慢,NFS操作更可能超时。如果软件是自动安装的,则可能是相关的目录在命令失败时不可用,但在命令成功时可用;我以前见过类似的问题。还有“如果你有足够的机器,一些总是失败的”综合症。与成千上万台机器一起工作,而不是数百台家用机器。 – 2014-10-20 22:29:48

(很抱歉,但我原来的答复是相当错误的......这是修正)

使用$?获得在startProcess.sh线索后台进程的退出状态到错误的结果。男人状态:

Special Parameters 
?  Expands to the status of the most recently executed foreground 
     pipeline. 

正如你在评论中提及获得后台进程的退出状态使用内置在wait的正确方法,但这种必须处理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>进行检查)。等待后台进程的退出状态存储在着名的$?伪变量中。

主脚本等待所有的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 

出射码被正确地报告可以看出。

我希望这可以帮助一下!

+0

感谢您的帮助,我做了你写的内容,如果'ps -p $ PID'的返回代码不是零 - >发生了这个过程,我还添加了一个等待该进程'wait $ PID'的等待。当我得到返回码时,我会在这里再次发帖 – Jan 2014-10-21 16:10:09

+0

@Jan:你能解决问题吗?什么是返回的错误代码? – TrueY 2014-10-24 09:30:37

+0

@Jan:你能解决这个问题吗?什么是返回的错误代码? – TrueY 2014-11-14 12:37:02