注意:我以为我正在使用bash,但/ bin / sh链接到/ bin / dash,这有一个奇怪的exec问题。
我在Linux上有一个简单的bash shell脚本用于启动服务器进程(我没有编写或控制),并希望让bash shell脚本将启动进程的PID输出到pid文件。
问题是bash-exec命令不会用启动的服务器进程替换它自己的进程!
所以:
echo $$ | cat > /var/run/launched-server.pid
这 not 不起作用,因为文件中的pid将是bash而不是服务器进程的pid。如果服务器进程退出bash可能不会退出,而愚蠢的启动脚本会在进程列表中挂起。
有没有人知道使用bash的方式(或者破折号可能?)以便:
编辑: 来自bash reference manual的此片段有用......
exec
exec [-cl] [-a name] [command [arguments]]
如果提供了命令,它将替换shell而不创建新进程。如果提供了-l选项,则shell会在传递给command的第0个参数的开头放置一个破折号。这是登录程序的功能。 -c选项导致在空环境中执行命令。如果提供了-a,则shell将name作为命令的第0个参数传递。如果未指定命令,则可以使用重定向来影响当前的shell环境。如果没有重定向错误,则返回状态为零;否则返回状态为非零。
编辑2: 这是脚本(已消毒):
#!/bin/sh
# this is where the server expects to run its services for Daemontools
SERVICE_DIR='/var/service';
# kill stdout, stderr, stdin
exec </dev/null
exec >/dev/null
exec 2>/dev/null
logger -ip daemon.debug -- stdout, stderr, stdin redirected to /dev/null
if [ -d $SERVICE_DIR ]; then
# sanitized...
logger -ip daemon.debug -- services and supervisors exited
else
logger -ip daemon.err -- $SERVICE_DIR does not exist, exiting
exit 1;
fi
if [ -d /var/run/pid ]; then
echo $$ | cat > /var/run/pid/launched-server.pid
logger -ip daemon.debug -- creating launched-server pidfile
fi
# start the server process
logger -ip daemon.info -- launching server on $SERVICE_DIR
exec /usr/local/bin/launched-server
有些ps输出可能更清楚了吗?
me@chainsaw: ~/dev $ ps ax | grep launched-server
13896 pts/1 S+ 0:00 /bin/sh ./server_boot
13905 pts/1 S+ 0:00 launched-server /var/service
13938 pts/2 R+ 0:00 grep --color=auto launched-server
答案 0 :(得分:2)
我现在意识到真正的问题是什么:
使用#!/bin/sh
我没有调用bash,而是破折号。
Dash的exec是具有exec问题的shell。如果我从一开始就使用过#!/bin/bash
,那就可以按预期工作了。
答案 1 :(得分:1)
您的发布内容是否包含start-stop-daemon(8)
?非常有用的小工具,它专门为从shell脚本启动守护进程而构建。 (当然,守护进程比shell脚本更长,所以它可能不是完美的匹配 - 这取决于你希望shell比你的守护进程更长的原因。)
或者,对于更简单的事情:
你的问题可以用bash的exec
命令解决吗?它用您要求执行的任何程序替换shell进程:
#!/bin/bash
echo $$ > /tmp/pidfile
exec /bin/sleep 60
$ ./show_exec.sh
[nothing happens]
而且,在另一个shell中:
$ cat pidfile
24686
$ ps auxw | grep 24686
sarnold 24686 0.0 0.0 9728 816 pts/1 S+ 04:53 0:00 /bin/sleep 60