bash函数的逻辑

时间:2014-11-25 15:25:26

标签: bash

我必须修复一个bash启动/停止脚本,但我对bash不是很了解。

脚本就像这样开始

name='basename $0'
pid_file="/home/$name.pid"
dir="/home/somedir"
user="someuser"
cmd="somecmd"

get_pid() {
  cat "$pid_file"
}

is_running() {
  [ -f "$pid_file" ] && ps `get_pid` > /dev/null 2>&1
}

case "$1" in
   start)
   if is_running; then
      echo "Already started"
   else
      echo "Starting $name"
      cd $dir
      sudo -u "$user" $cmd >> "$stdout_log" 2>> "$dtderr_log" &
      echo $! > "$pid_file"
      if ! is_running; then
          echo "Unable to start, see $stdout_log" 2>> "$stderr_log" &
          exit 1
      fi
   fi

is_running()如何运作?它似乎返回一个布尔值,但我不理解逻辑。 sudo命令正确启动进程,但它总是报告它无法启动,因为is_running为false

2 个答案:

答案 0 :(得分:2)

正如约翰库格曼指出的那样,你可以从他的链接中得到一些暗示,尽管不是一切。函数is_running中的逻辑很简单,首先检查具有进程id(pid)的文件是否存在:

[ -f "$pid_file" ]

如果确实存在,则返回0,否则返回1。和&&然后检查前一个命令是否成功(返回0)并执行&&当且仅当前一个命令返回0.下一个命令:

ps 'get_pid'

使用函数get_pid(文件中的文本)列出使用pid运行的进程。如果使用提供的pid的进程正在运行,则此命令的计算结果为0;如果没有,则此计算结果为1。功能的最后一部分:

 > /dev/null 2>&1

重定向命令ps' get_pid'的输出。 to null和终端的任何错误(标准输出)。

总之,如果存储pid的文件,则is_running将返回0(如true),并且此文件中的pid是ps所见的当前正在运行的进程。

答案 1 :(得分:2)

实际上你想知道三件事:1。如果给定的PID正在运行,2。如果它是你的进程,3。如果它是正确的程序。请使用-s获取非空文件。

is_running() {
  [ -s "$pid_file" ] && kill -0 $(< $pid_file)
}

kill -0检查,如果进程正在运行且是否是您的进程。

$ kill -0 $$                 # checking for the current bash - this should always work
$ kill -0 12345              # this process does not exist
bash: kill: (12345) - No such process
$

另一种选择是pgrep,这将涵盖所有三件事。请使用-s获取非空文件。

is_running() {
  [ -s "$pid_file" ] && pgrep -U "$user" -fl "$cmd" -P $(< $pid_file)
}

如果你开始一个新的过程,最好使用像这样的包装器

#!/bin/bash
echo $$ > pidfile
exec process

魔术#!启动bash,bash知道自己的PID,并将此PID写入文件。 现在exec用新的替换bash进程 - 这样,进程id(PID)保持不变!

改进了变体pidstarter.bash

#!/bin/bash
echo $$ > "$1"
shift
exec "$@"

现在这个开始新进程,第一个参数是pidfile。

所以不是这两行

sudo -u "$user" $cmd >> "$stdout_log" 2>> "$dtderr_log" &
echo $! > "$pid_file"

我会用

sudo -u "$user" pidstarter.bash "$pid_file" $cmd &
sleep 1 # let there enough time to start bash and write pidfile