如何查找 dash-exec 命令的 PID
注意:我以为我使用的是 bash,但 /bin/sh 链接到 /bin/dash,它有这个奇怪的执行问题。
我在 Linux 上有一个简单的 bash shell 脚本,用于启动服务器进程(我没有编写或控制),并且希望 bash shell 脚本将启动的进程的 PID 输出到 pidfile。
问题是 bash-exec 命令不会用启动的服务器进程替换它自己的进程!
所以:
echo $$ | cat > /var/run/launched-server.pid
这不起作用,因为文件中的pid将是bash的pid而不是服务器进程的pid。如果服务器进程退出,bash 可能不会退出,而愚蠢的启动脚本会挂在进程列表中。
有谁知道如何使用 bash (或 dash ?) 这样:
- 可能吗?
- 启动的服务器服务器进程的PID将在我的pid文件中?
- 确保 bash 脚本会在启动服务器存在时终止,并且不会让失效的 shell 进程挂在进程列表中?
编辑: bash 参考手册中的这段代码很有用...
exec
exec [-cl] [-a name] [command [arguments]]
如果提供命令,它将替换 shell,而不创建新进程。如果提供了 -l 选项,shell 会在传递给命令的第 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
NOTE: I thought I was using bash, but /bin/sh is linked to /bin/dash, which has this weird exec problem.
I have a simple bash shell script on Linux which is used to launch a server process (which I did not write or control) and would like to have the bash shell script output the launched process's PID to a pidfile.
The problem is that bash-exec command does not replace its own process with the launched server process!
So:
echo $ | cat > /var/run/launched-server.pid
This does not work because the pid in the file will be that of bash not the server process. And if the server process exits bash may not exit leaving the stupid launch script hanging out in the process list.
Does anyone know a way to use bash (or dash maybe?) so that:
- Is it possible?
- The launched-server server process's PID will be in my pidfile?
- Ensure that the bash script will die when the launched-server exists and not leave defunct shell processes hanging out in the process list?
Edit:
This snippet from the bash reference manual be of use...
exec
exec [-cl] [-a name] [command [arguments]]
If command is supplied, it replaces the shell without creating a new process. If the -l option is supplied, the shell places a dash at the beginning of the zeroth argument passed to command. This is what the login program does. The -c option causes command to be executed with an empty environment. If -a is supplied, the shell passes name as the zeroth argument to command. If no command is specified, redirections may be used to affect the current shell environment. If there are no redirection errors, the return status is zero; otherwise the return status is non-zero.
Edit 2:
This is the script (sanitized):
#!/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
And some ps output to maybe be more clear?
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我现在意识到真正的问题是什么:
通过使用
#!/bin/sh
,我没有调用bash,而是调用dash。Dash 的 exec 是存在 exec 问题的 shell。如果我从一开始就使用
#!/bin/bash
,它就会按预期工作。I now realize what the real problem was:
By using
#!/bin/sh
I was not invoking bash, but dash.Dash's exec is the shell with the exec problem. If I had used
#!/bin/bash
from the start, it would have worked as expected.您的发行版是否包含
start-stop-daemon(8)
?非常有用的小工具,它是专门为从 shell 脚本启动守护进程而构建的。 (当然,守护进程的寿命比 shell 脚本长,所以它可能不是完美的匹配——这取决于您为什么希望 shell 比守护进程寿命长。)或者,对于更简单的事情:
您的问题可以用 bash 的
执行命令?它将 shell 进程替换为您要求执行的任何程序:
并且,在另一个 shell 中:
Does your distribution include
start-stop-daemon(8)
? Wonderfully useful little tool, it was built specifically for starting daemons from shell scripts. (Of course, the daemons outlive the shell scripts, so it may not be a perfect match -- it depends on why you want the shell to outlive your daemon.)Or, for something simpler:
Could your problem be solved with bash's
exec
command? It replaces the shell process with whatever program you ask to execute:And, in another shell: