# 脚本作为daemon运行

在一些测试情况下，需要验证进程的继承关系，所以想能够持续运行一个脚本，作为daemon。

## 使用`setsid`运行脚本作为daemon

要使得一个shell按照daemon方式运行，需要使用`setsid`（`setsid - run a program in a new session`）并将输出重定向。可以将输出重定向到一个认知文件，或者`/dev/null`抛弃日志。

假设这里我们有一个 `test_daemon.sh` 脚本内容如下

```bash
#!/bin/bash

while true; do
  /bin/echo "run as daemon then sleep 10s"
  /bin/date > /dev/shm/test_daemon
  /bin/sleep 10
done
```

则我们可以如下方式执行

```bash
setsid test_daemon.sh >/dev/null 2>&1 < /dev/null &
```

但是发现这个`test_daemon.sh`并没有如料想的一样运行，而是检查进程发现结束了

```bash
$ps aux | grep test_daemon
admin    220955  0.0  0.0  61200   756 pts/0    S+   14:39   0:00 grep test_daemon
[1]+  Done                    setsid test_daemon.sh > /dev/null 2>&1 < /dev/null
```

将`/dev/null`替换成本地的一个日志文件`/home/admin/test_daemon.log`，看输出情况

```bash
setsid test_daemon.sh > /home/admin/test_daemon.log 2>&1 < /home/admin/test_daemon.log &
```

可以看到 `test_daemon.log` 中有一行记录

```
execvp: No such file or directory
```

这个问题似乎和终端有关，是执行脚本命令需要tty么？

## 使用`daemon`工具

> 参考 [Using Daemon to create Linux services in 5 minutes](http://blog.terminal.com/using-daemon-to-daemonize-your-programs/) - 这篇文章解释非常透彻清晰

[daemon](http://www.libslack.org/daemon/)是一个将其他进程转换成daemon运行的工具，安装方法可以参考[README](http://libslack.org/daemon/README)。可以直接从从官网下载源代码安装，或者使用rpm安装。

```bash
wget http://libslack.org/daemon/download/daemon-0.6.4.tar.gz
tar xfz daemon-0.6.4.tar.gz
cd daemon-0.6.4
./config
make
sudo make install
```

> `make test`是用来检测`libslack`，不确定用途

使用方法非常简单，假设这里运行一个`test_daemon_10.sh`脚本

```bash
daemon -r /home/admin/test_daemon_10.sh
```

实验用的`test_daemon_10.sh`内容如下

```bash
#!/bin/bash

rm -f /dev/shm/test_daemon

i=0
while true; do
  /bin/echo "run as daemon then sleep 10s"
  /bin/date >> /dev/shm/test_daemon
  /bin/sleep 10
  echo "Hello world - $i" >> /dev/shm/test_daemon
  i=$(( $i + 1 ))
done
```

> 这个脚本唯一的功能就是不断循环并将输出记录到`/dev/shm/test_daemon`文件。

使用`daemon -r`参数，这个`-r`参数表示`respawn`，也就是自动重新重启。表示当脚本被杀死以后，`daemon`会自动再启动这个脚本作为服务。

下面我们来检验一下，先检查脚本进程

```bash
ps aux | grep test_daemon_10 | grep -v grep
```

可以看到

```bash
admin     45747  0.0  0.0  65400   424 ?        S    09:49   0:00 daemon -r /home/admin/test_daemon_10.sh
admin     45749  0.0  0.0  63872  1076 ?        S    09:49   0:00 /bin/bash /home/admin/test_daemon_10.sh
```

我们杀死进程`45749`

```bash
kill 45749
```

然后再使用命令`ps aux | grep test_daemon_10 | grep -v grep` 检查系统中的`test_daemon_10`，可以看到脚本进程已经杀死

```bash
admin     45747  0.0  0.0  65400   436 ?        S    09:49   0:00 daemon -r /home/admin/test_daemon_10.sh
admin     45749  0.0  0.0      0     0 ?        Z    09:49   0:00 [test_daemon_10.] <defunct>
```

过一会，我们再次使用命令 `ps aux | grep test_daemon_10 | grep -v grep` 就会发现脚本再次被`daemon`进程启动（注意进程号不同了）

```bash
admin     45747  0.0  0.0  65428   680 ?        S    09:49   0:00 daemon -r /home/admin/test_daemon_10.sh
admin     98336  0.0  0.0  63872  1068 ?        S    09:57   0:00 /bin/bash /home/admin/test_daemon_10.sh
```

这个daemon化的脚本会一直运行，即使关闭终端窗口。

> [Using Daemon to create Linux services in 5 minutes](http://blog.terminal.com/using-daemon-to-daemonize-your-programs/)还提供了SysVinit兼容的启动脚本用于`daemonize`脚本。

## 使用脚本functions来管理daemon(Red Hat/CentOS系使用)

Red Hat系发行版提供了一个标准化的`/etc/init.d/functions`来管理daemon脚本。

## 参考

* [Run bash script as daemon](http://stackoverflow.com/questions/19233529/run-bash-script-as-daemon)
* [Using Daemon to create Linux services in 5 minutes](http://blog.terminal.com/using-daemon-to-daemonize-your-programs/)
* [Managing Linux daemons with init scripts](https://www.linux.com/learn/tutorials/442412-managing-linux-daemons-with-init-scripts)
* [How can I run a shell script as a daemon under Redhat?](http://unix.stackexchange.com/questions/72881/how-can-i-run-a-shell-script-as-a-daemon-under-redhat)
* [How to start Script as Daemon – DEBIAN – UBUNTU](http://ram.kossboss.com/start-script-daemon-debian-ubuntu/)
* [Best way to make a shell script daemon?](http://stackoverflow.com/questions/3430330/best-way-to-make-a-shell-script-daemon) - 提到了[Unix Programming FAQ](http://www.faqs.org/faqs/unix-faq/programmer/faq/)有关案例
* [Beginners Guide to creating a daemon in Linux](http://shahmirj.com/blog/beginners-guide-to-creating-a-daemon-in-linux) - 一个简单的c语言写的daemon，可参考


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://huataihuang.gitbook.io/cloud-atlas-draft/develop/shell/utilities/run_script_as_daemon.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
