如何在 unix 中守护任意脚本? [英] How do I daemonize an arbitrary script in unix?

查看:20
本文介绍了如何在 unix 中守护任意脚本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要一个守护进程,它可以将任意的通用脚本或命令转换为 守护进程.

I'd like a daemonizer that can turn an arbitrary, generic script or command into a daemon.

我想处理两种常见情况:

There are two common cases I'd like to deal with:

  1. 我有一个应该永远运行的脚本.如果它死了(或在重新启动时),请重新启动它.不要让两个副本同时运行(检测一个副本是否已经在运行,在这种情况下不要启动它).

  1. I have a script that should run forever. If it ever dies (or on reboot), restart it. Don't let there ever be two copies running at once (detect if a copy is already running and don't launch it in that case).

我有一个简单的脚本或命令行命令,我想永远重复执行(在运行之间有短暂的停顿).同样,不要让脚本的两个副本同时运行.

I have a simple script or command line command that I'd like to keep executing repeatedly forever (with a short pause between runs). Again, don't allow two copies of the script to ever be running at once.

当然,在案例 2 中围绕脚本编写一个while(true)"循环然后应用案例 1 的解决方案是微不足道的,但更通用的解决方案将直接解决案例 2,因为这适用于脚本情况 1 也是如此(如果脚本不打算永远消失,您可能只想要更短的暂停或没有暂停(当然,如果脚本真的确实永远不会消失,那么暂停实际上并不重要)).

Of course it's trivial to write a "while(true)" loop around the script in case 2 and then apply a solution for case 1, but a more general solution will just solve case 2 directly since that applies to the script in case 1 as well (you may just want a shorter or no pause if the script is not intended to ever die (of course if the script really does never die then the pause doesn't actually matter)).

请注意,解决方案不应涉及,例如,向现有脚本添加文件锁定代码或 PID 记录.

Note that the solution should not involve, say, adding file-locking code or PID recording to the existing scripts.

更具体地说,我想要一个程序守护进程",我可以像这样运行

More specifically, I'd like a program "daemonize" that I can run like

% daemonize myscript arg1 arg2

或者,例如,

% daemonize 'echo `date` >> /tmp/times.txt'

将不断增加的日期列表附加到 times.txt.(请注意,如果 daemonize 的参数是一个永远运行的脚本,如上面的情况 1,那么 daemonize 仍然会做正确的事情,必要时重新启动它.)然后我可以在我的 .login 中放置一个类似上面的命令和/或每小时或每分钟 cron 一次(取决于我对它意外死亡的担心程度).

which would keep a growing list of dates appended to times.txt. (Note that if the argument(s) to daemonize is a script that runs forever as in case 1 above, then daemonize will still do the right thing, restarting it when necessary.) I could then put a command like above in my .login and/or cron it hourly or minutely (depending on how worried I was about it dying unexpectedly).

注意:daemonize 脚本需要记住它正在守护的命令字符串,以便如果相同的命令字符串再次被守护,它不会启动第二个副本.

NB: The daemonize script will need to remember the command string it is daemonizing so that if the same command string is daemonized again it does not launch a second copy.

此外,理想情况下,该解决方案应该适用于 OS X 和 Linux,但欢迎使用适用于其中之一的解决方案.

Also, the solution should ideally work on both OS X and linux but solutions for one or the other are welcome.

如果您必须使用 sudo daemonize myscript myargs 调用它就好了.

It's fine if you have to invoke it with sudo daemonize myscript myargs.

(如果我认为这一切都是错误的,或者有快速而肮脏的部分解决方案,我也很想听听.)

(If I'm thinking of this all wrong or there are quick-and-dirty partial solutions, I'd love to hear that too.)

PS:如果有用,这里是python特有的类似问题.

PS: In case it's useful, here's a similar question specific to python.

this 对类似问题的回答似乎是对任意脚本进行快速和肮脏妖魔化的有用习语:

And this answer to a similar question has what appears to be a useful idiom for a quick-and-dirty demonizing of an arbitrary script:

推荐答案

您可以使用 nohup 和 & 来守护 Unix 中的任何可执行文件.操作员:

You can daemonize any executable in Unix by using nohup and the & operator:

nohup yourScript.sh script args&

nohup 命令允许你关闭你的 shell 会话而不杀死你的脚本,而 &将您的脚本置于后台,以便您获得 shell 提示以继续您的会话.唯一的小问题是标准输出和标准错误都被发送到 ./nohup.out,所以如果你在这个庄园启动几个脚本,它们的输出将交织在一起.更好的命令是:

The nohup command allows you to shut down your shell session without it killing your script, while the & places your script in the background so you get a shell prompt to continue your session. The only minor problem with this is standard out and standard error both get sent to ./nohup.out, so if you start several scripts in this manor their output will be intertwined. A better command would be:

nohup yourScript.sh script args >script.out 2>script.error&

这会将标准输出发送到您选择的文件,并将标准错误发送到您选择的其他文件.如果您只想对标准输出和标准错误使用一个文件,您可以使用以下方法:

This will send standard out to the file of your choice and standard error to a different file of your choice. If you want to use just one file for both standard out and standard error you can us this:

nohup yourScript.sh script args >script.out 2>&1 &

2>&1 告诉 shell 将标准错误(文件描述符 2)重定向到与标准输出(文件描述符 1)相同的文件.

The 2>&1 tells the shell to redirect standard error (file descriptor 2) to the same file as standard out (file descriptor 1).

要只运行一次命令并在它死掉时重新启动它,您可以使用此脚本:

To run a command only once and restart it if it dies you can use this script:

#!/bin/bash

if [[ $# < 1 ]]; then
    echo "Name of pid file not given."
    exit
fi

# Get the pid file's name.
PIDFILE=$1
shift

if [[ $# < 1 ]]; then
    echo "No command given."
    exit
fi

echo "Checking pid in file $PIDFILE."

#Check to see if process running.
PID=$(cat $PIDFILE 2>/dev/null)
if [[ $? = 0 ]]; then
    ps -p $PID >/dev/null 2>&1
    if [[ $? = 0 ]]; then
        echo "Command $1 already running."
        exit
    fi
fi

# Write our pid to file.
echo $$ >$PIDFILE

# Get command.
COMMAND=$1
shift

# Run command until we're killed.
while true; do
    $COMMAND "$@"
    sleep 10 # if command dies immediately, don't go into un-ctrl-c-able loop
done

第一个参数是要使用的 pid 文件的名称.第二个参数是命令.所有其他参数都是命令的参数.

The first argument is the name of the pid file to use. The second argument is the command. And all other arguments are the command's arguments.

如果您将此脚本命名为 restart.sh,您会这样称呼它:

If you name this script restart.sh this is how you would call it:

nohup restart.sh pidFileName yourScript.sh script args >script.out 2>&1 &

这篇关于如何在 unix 中守护任意脚本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆