如何在Bash脚本中正确查找、停止并重启树莓派上的Motion进程?
解决Bash脚本终止Motion进程后自身退出的问题
问题根源
你遇到的问题是因为pgrep -f motion会匹配所有命令行包含"motion"字符串的进程,包括当前正在运行的这个脚本(脚本内容里有motion相关命令,进程列表中会显示脚本的执行路径及相关内容)。执行kill时会把脚本自身的PID也杀掉,导致脚本直接终止,后续的sleep、echo和重启命令都无法执行。
正确的实现方法
方法1:精确匹配进程名(推荐)
使用pgrep -x motion,-x参数表示精确匹配进程名,只查找进程名严格等于motion的进程,不会匹配脚本自身:
#!/bin/bash # 查找并重启motion进程 MOTION_PID=$(pgrep -x motion) # 先判断进程是否存在,避免kill空值报错 if [ -n "$MOTION_PID" ]; then sudo kill "$MOTION_PID" sleep 5 fi echo "restarting" sudo motion -b -c ~/.motion/motion.conf
方法2:排除脚本自身PID
如果必须使用-f参数(比如需要匹配带特定参数的motion进程),可以通过$$(当前脚本的PID)过滤掉自身:
#!/bin/bash # 查找并重启motion进程 # 获取所有含motion的PID,排除当前脚本PID MOTION_PIDS=$(pgrep -f motion | grep -v $$) if [ -n "$MOTION_PIDS" ]; then sudo kill $MOTION_PIDS sleep 5 fi echo "restarting" sudo motion -b -c ~/.motion/motion.conf
方法3:使用pidof命令
pidof默认只匹配进程名,效果和pgrep -x一致:
#!/bin/bash # 查找并重启motion进程 MOTION_PID=$(pidof motion) if [ -n "$MOTION_PID" ]; then sudo kill "$MOTION_PID" sleep 5 fi echo "restarting" sudo motion -b -c ~/.motion/motion.conf
额外优化
如果kill后需要确保进程完全退出,可以改用kill -TERM(默认就是TERM信号),或者等待进程退出后再执行重启:
#!/bin/bash MOTION_PID=$(pgrep -x motion) if [ -n "$MOTION_PID" ]; then sudo kill "$MOTION_PID" # 等待进程退出,最多等10秒 for i in {1..10}; do if ! pgrep -x motion > /dev/null; then break fi sleep 1 done fi echo "restarting" sudo motion -b -c ~/.motion/motion.conf
内容的提问来源于stack exchange,提问作者NigelS
相关产品推荐
相关产品推荐

