【发布时间】:2012-02-25 09:54:54
【问题描述】:
我需要一个独立于平台的 (Linux/Unix|OSX) shell/bash 命令来确定特定进程是否正在运行。例如mysqld, httpd...
最简单的方法/命令是什么?
【问题讨论】:
标签: linux bash shell unix process
我需要一个独立于平台的 (Linux/Unix|OSX) shell/bash 命令来确定特定进程是否正在运行。例如mysqld, httpd...
最简单的方法/命令是什么?
【问题讨论】:
标签: linux bash shell unix process
在大多数 Linux 发行版上,您可以使用 pidof(8)。
它将打印指定进程的所有正在运行的实例的进程ID,如果没有实例正在运行,则不打印。
例如,在我的系统上(我有四个 bash 实例和一个 remmina 实例正在运行):
$ pidof bash remmina
6148 6147 6144 5603 21598
在其他 Unices 上,pgrep 或 ps 和 grep 的组合将达到同样的效果,正如其他人正确指出的那样。
【讨论】:
pidof httpd 在 Red Hat 5 上运行良好。但在我的 Red Hat 4 上,pidof 不存在 :-(
我使用pgrep -l httpd,但不确定它是否存在于任何平台上...
谁可以在 OSX 上确认?
【讨论】:
pidof吗?好的,你做到了。谢谢你。所以我们应该在 OSX 上找到其他工作......你的基本 ps|grep 可能是唯一的解决方案;-)
这应该适用于大多数版本的 Unix、BSD 和 Linux:
PATH=/usr/ucb:${PATH} ps aux | grep httpd | grep -v grep
测试日期:
PATH=...]【讨论】:
ps。为了避免第二个grep,我建议:ps aux | grep [h]ttpd
grep。
虽然pidof 和pgrep 是确定正在运行的内容的绝佳工具,但遗憾的是,它们在某些操作系统上均不可用。一个明确的故障保险是使用以下内容:ps cax | grep command
Gentoo Linux 上的输出:
14484 ? S 0:00 阿帕奇2 14667 ? S 0:00 阿帕奇2 19620 ? SL 0:00 阿帕奇2 21132 ? SS 0:04 阿帕奇2OS X 上的输出:
42582 ?? Z 0:00.00 (smbclient) 46529 ?? Z 0:00.00 (smbclient) 46539 ?? Z 0:00.00 (smbclient) 46547 ?? Z 0:00.00 (smbclient) 46586 ?? Z 0:00.00 (smbclient) 46594 ?? Z 0:00.00 (smbclient)在 Linux 和 OS X 上,grep 都会返回一个退出代码,因此很容易检查是否找到了进程:
#!/bin/bash
ps cax | grep httpd > /dev/null
if [ $? -eq 0 ]; then
echo "Process is running."
else
echo "Process is not running."
fi
此外,如果您想要 PID 列表,您也可以轻松地使用 grep 搜索:
ps cax | grep httpd | grep -o '^[ ]*[0-9]*'
谁的输出在 Linux 和 OS X 上是一样的:
3519 3521 3523 3524
以下的输出是一个空字符串,使得这种方法对于未运行的进程是安全的:
回声ps cax | grep aasdfasdf | grep -o '^[ ]*[0-9]*'
这种方法适用于编写简单的空字符串测试,然后甚至遍历发现的 PID。
#!/bin/bash
PROCESS=$1
PIDS=`ps cax | grep $PROCESS | grep -o '^[ ]*[0-9]*'`
if [ -z "$PIDS" ]; then
echo "Process not running." 1>&2
exit 1
else
for PID in $PIDS; do
echo $PID
done
fi
您可以通过将其保存到具有执行权限(chmod +x running)的文件(名为“running”)并使用参数执行它来测试它:./running "httpd"
#!/bin/bash
ps cax | grep httpd
if [ $? -eq 0 ]; then
echo "Process is running."
else
echo "Process is not running."
fi
警告!!!
请记住,您只是在解析 ps ax 的输出,这意味着,正如 Linux 输出中所见,它不仅匹配进程,还匹配传递给该程序的参数。我强烈建议在使用此方法时尽可能具体(例如,./running "mysql" 也将匹配 'mysqld' 进程)。我强烈建议尽可能使用which 检查完整路径。
参考资料:
【讨论】:
grep 也会发现自己正在运行(例如,ps cax | grep randomname 将始终返回 0,因为 grep 会找到 grep randomname(希望这很清楚......)。一种解决方法是添加方括号围绕进程名称的第一个字母,例如ps cax | grep [r]andomname。
ps cax | rev | cut -f1 -d' ' | rev 将只显示名称列,以便于解析。
ps cax 可能无法完整输出命令名称。例如,它打印“chromium-browse”而不是“chromium-browser”。
只是一个小补充:如果您将-c 标志添加到ps,则不需要删除包含带有grep -v 的grep 进程的行。即
ps acux | grep cron
这是您在 bsd-ish 系统(包括 MacOSX)上需要的所有类型,如果您需要的信息较少,您可以离开 -u。
在原生 ps 命令的遗传学指向 SysV 的系统上,您会使用
ps -e |grep cron
或
ps -el |grep cron
列表包含的不仅仅是 pid 和进程名称。当然,您可以使用-o <field,field,...> 选项选择要打印的特定字段。
【讨论】:
最简单的方法是使用ps和grep:
command="httpd"
running=`ps ax | grep -v grep | grep $command | wc -l`
if [ running -gt 0 ]; then
echo "Command is running"
else
echo "Command is not running"
fi
如果你的命令有一些命令参数,那么你也可以在 'grep $command' 后面加上更多的 'grep cmd_arg1' 来过滤掉你不感兴趣的其他可能的进程。
示例:如果有任何带有提供参数的 java 进程,请告诉我:
-Djava.util.logging.config.file=logging.properties
正在运行
ps ax | grep -v grep | grep java | grep java.util.logging.config.file=logging.properties | wc -l
【讨论】:
ps cax就不需要使用grep -v了。例如,您可以使用:ps cax | grep java > /dev/null || echo "Java not running".
通过尝试对进程参数(如pgrep "mysqld")进行某种模式识别来查找进程是一种迟早注定要失败的策略。如果你有两个 mysqld 正在运行怎么办?忘记那种方法。你可能暂时做对了,它可能会工作一两年,但随后会发生一些你没有想到的事情。
只有进程 id (pid) 是真正唯一的。
当您在后台启动某些内容时,请始终存储 pid。在 Bash 中,这可以通过 $! Bash 变量来完成。这样做可以省去很多麻烦。
所以现在的问题变成了如何知道 pid 是否正在运行。
简单地做:
ps -o pid= -p这是 POSIX,因此是可移植的。如果进程正在运行,它将返回 pid 本身,如果进程未运行,它将不返回任何内容。严格来说,该命令将返回单个列,pid,但由于我们给出了一个空标题标题(紧接在等号之前的内容)并且这是唯一请求的列,因此 ps 命令将不会使用标题一点也不。这是我们想要的,因为它使解析更容易。
这适用于 Linux、BSD、Solaris 等。
另一种策略是测试上述ps 命令的退出值。如果进程正在运行,它应该是零,如果不是,它应该是非零。 POSIX 规范说,如果发生错误,ps 必须退出 >0,但我不清楚什么是“错误”。因此,尽管我很确定它在所有 Unix/Linux 平台上都能正常工作,但我个人并没有使用该策略。
【讨论】:
grep <sometext> 才能找到给定流程的情况,那么您在开始流程时做错了, 恕我直言。我从 OP 的问题中得知,他确实可以控制流程的启动方式。
这种方法可以在“ps”、“pidof”和rest命令不可用的情况下使用。 我个人在我的工具/脚本/程序中经常使用 procfs。
egrep -m1 "mysqld$|httpd$" /proc/[0-9]*/status | cut -d'/' -f3
小解释是怎么回事:
【讨论】:
以下 shell 函数仅基于 POSIX 标准命令和选项,应该适用于大多数(如果没有的话)Unix 和 linux 系统。 :
isPidRunning() {
cmd=`
PATH=\`getconf PATH\` export PATH
ps -e -o pid= -o comm= |
awk '$2 ~ "^.*/'"$1"'$" || $2 ~ "^'"$1"'$" {print $1,$2}'
`
[ -n "$cmd" ] &&
printf "%s is running\n%s\n\n" "$1" "$cmd" ||
printf "%s is not running\n\n" $1
[ -n "$cmd" ]
}
$ isPidRunning httpd
httpd is running
586 /usr/apache/bin/httpd
588 /usr/apache/bin/httpd
$ isPidRunning ksh
ksh is running
5230 ksh
$ isPidRunning bash
bash is not running
请注意,当传递可疑的“0]”命令名称时,它会阻塞,并且也无法识别名称中包含嵌入空格的进程。
还要注意,最受支持和接受的解决方案需要不可移植的 ps 选项,并且无偿使用 shell,尽管它很受欢迎,但不能保证在每台 Unix/Linux 机器上都存在 (bash)
【讨论】:
$ isPidRunning 0] 打印例如“0] 正在运行 3 [ksoftirqd/0] 8 [rcuop/0] 17 [rcuos/0] 26 [rcuob/0] 34 [migration/0] 35 [watchdog/0]”在这里。
将各种建议放在一起,我能想到的最简洁的版本(没有触发部分单词的不可靠 grep)是:
kill -0 $(pidof mysql) 2> /dev/null || echo "Mysql ain't runnin' message/actions"
kill -0 不会杀死进程,但会检查它是否存在,然后返回 true,如果您的系统上没有 pidof,请在启动进程时存储 pid:
$ mysql &
$ echo $! > pid_stored
然后在脚本中:
kill -0 $(cat pid_stored) 2> /dev/null || echo "Mysql ain't runnin' message/actions"
【讨论】:
这将打印基本名称为“chromium-browser”的进程数:
ps -e -o args= | awk 'BEGIN{c=0}{
if(!match($1,/^\[.*\]$/)){sub(".*/","",$1)} # Do not strip process names enclosed by square brackets.
if($1==cmd){c++}
}END{print c}' cmd="chromium-browser"
如果打印“0”,则进程没有运行。该命令假定进程路径不包含中断空间。我没有用挂起的进程或僵尸进程对此进行测试。
使用gwak 作为 Linux 中的awk 替代品进行了测试。
这是一个更通用的解决方案,并带有一些示例用法:
#!/bin/sh
isProcessRunning() {
if [ "${1-}" = "-q" ]; then
local quiet=1;
shift
else
local quiet=0;
fi
ps -e -o pid,args= | awk 'BEGIN{status=1}{
name=$2
if(name !~ /^\[.*\]$/){sub(".*/","",name)} # strip dirname, if process name is not enclosed by square brackets.
if(name==cmd){status=0; if(q){exit}else{print $0}}
}END{exit status}' cmd="$1" q=$quiet
}
process='chromium-browser'
printf "Process \"${process}\" is "
if isProcessRunning -q "$process"
then printf "running.\n"
else printf "not running.\n"; fi
printf "Listing of matching processes (PID and process name with command line arguments):\n"
isProcessRunning "$process"
【讨论】:
当您启动它时,它的 PID 将记录在 $! 变量中。将此 PID 保存到文件中。
然后您将需要检查此 PID 是否对应于正在运行的进程。这是一个完整的骨架脚本:
FILE="/tmp/myapp.pid"
if [ -f $FILE ];
then
PID=$(cat $FILE)
else
PID=1
fi
ps -o pid= -p $PID
if [ $? -eq 0 ]; then
echo "Process already running."
else
echo "Starting process."
run_my_app &
echo $! > $FILE
fi
基于peterh 的answer。知道给定 PID 是否正在运行的诀窍在于 ps -o pid= -p $PID 指令。
【讨论】:
这是我的版本。特点:
脚本:
#!/bin/bash
# $1 - cmd
# $2 - args
# return: 0 - no error, running; 1 - error, not running
function isRunning() {
for i in $(pidof $1); do
cat /proc/$i/cmdline | tr '\000' ' ' | grep -F -e "$2" 1>&2> /dev/null
if [ $? -eq 0 ]; then
return 0
fi
done
return 1
}
isRunning java "-Djava.util.logging.config.file=logging.properties"
if [ $? -ne 0 ]; then
echo "not running, starting..."
fi
【讨论】:
没有一个答案对我有用,所以这是我的:
process="$(pidof YOURPROCESSHERE|tr -d '\n')"
if [[ -z "${process// }" ]]; then
echo "Process is not running."
else
echo "Process is running."
fi
解释:
|tr -d '\n'
这将删除终端创建的回车。其余的可以this发帖解释。
【讨论】:
[ $pid ] && [ -d /proc/$pid ] && command 如果你知道 pid
【讨论】: