【发布时间】:2017-06-02 18:52:03
【问题描述】:
我编写了我的第一个 bash 脚本,它使用“inotify”函数检查文件夹的更改并启动一些操作。整个进程由nohup作为后台进程运行。
该文件夹是多个 Datalogger 的目的地,它们通过 ftp 将 zip 格式的文件推送到不同的子文件夹中。 bash 脚本解压缩文件并随后启动一个 php 脚本,该脚本正在处理 zip 文件的内容。
我的问题:有时 bash 脚本会给我如下错误:
- No zipfiles found.
- unzip: cannot find zipfile...
这不应该发生,因为文件存在并且我可以在终端中运行相同的命令而不会出错。我之前遇到过同样的问题,当时我多次运行脚本时,所以我想这是导致问题的原因。
我尝试使用位于我的主目录中的 PID 文件来解决问题。出于某种原因,它仍然运行 bash 脚本的两个实例。如果我尝试运行另一个实例,它会按预期显示警告“进程已在运行”(参见程序代码)。当我手动终止第二个实例的进程(kill $$)时,它会在一段时间后重新启动,并且再次运行该进程的两个实例。
#!/bin/bash
PIDFILE=/home/PIDs/myscript.pid
if [ -f $PIDFILE ]
then
PID=$(cat $PIDFILE)
ps -p $PID > /dev/null 2>&1
if [ $? -eq 0 ]
then
echo "Process already running"
exit 1
else
## Process not found assume not running
echo $$ > $PIDFILE
if [ $? -ne 0 ]
then
echo "Could not create PID file"
exit 1
fi
fi
else
echo $$ > $PIDFILE
if [ $? -ne 0 ]
then
echo "Could not create PID file"
exit 1
fi
fi
while true;
do inotifywait -q -r -e move -e create --format %w%f /var/somefolder | while read FILE
do
dir=$(dirname $FILE)
filename=${FILE:$((${#dir}+1))}
if [[ "$filename" == *.zip ]];
then
unzip $FILE
php somephpscript $dir
fi
done
done
ps -ef 的输出如下所示:
UID PID PPID C STIME TTY TIME CMD
root 1439 1433 0 11:19 pts/0 00:00:00 /bin/bash /.../my_script
root 3488 1439 0 15:10 pts/0 00:00:00 /bin/bash /.../my_script
如您所见,第二个实例 Parent-PID 是脚本本身
编辑:我按照 Fred 的建议更改了 bash 脚本。源代码现在看起来像这样:
#!/bin/bash
PIDFILE=/home/PIDs/myscript.pid
if [ -f $PIDFILE ]
then
PID=$(cat $PIDFILE)
ps -p $PID > /dev/null 2>&1
if [ $? -eq 0 ]
then
echo "Process already running"
exit 1
else
## Process not found assume not running
echo $$ > $PIDFILE
if [ $? -ne 0 ]
then
echo "Could not create PID file"
exit 1
fi
fi
else
echo $$ > $PIDFILE
if [ $? -ne 0 ]
then
echo "Could not create PID file"
exit 1
fi
fi
while read -r FILE
do
dir=$(dirname $FILE)
filename=${FILE:$((${#dir}+1))}
if [[ "$filename" == *.zip ]];
then
unzip $FILE
php somephpscript $dir
fi
done < <(inotifywait -q -m -r -e move -e create --format %w%f /var/somefolder)
ps -ef 的输出仍然显示两个实例:
UID PID PPID C STIME TTY TIME CMD
root 7550 7416 0 15:59 pts/0 00:00:00 /bin/bash /.../my_script
root 7553 7550 0 15:59 pts/0 00:00:00 /bin/bash /.../my_script
root 7554 7553 0 15:59 pts/0 00:00:00 inotifywait -q -m -r -e move -e create --format %w%f /var/somefolder
【问题讨论】:
-
您是说脚本在第二次启动时会显示警告消息,然后在“exit 1”语句之后不会停止?如果你真的在交互式 shell 中尝试“杀死 $$”,那什么也做不了,因为 $$ 是 shell 的 PID,而 shell 发送自己的信号什么都不做。
-
我必须说第一个剧本相当有野心!在单括号条件 [ ] 中,您应该始终引用变量,例如 [ -f "$PIDFILE" ]。好吧,你应该到处引用它们。通常建议您使用小写的变量名以避免与环境变量冲突(尽管我已经知道自己忽略了这一点......)。
-
@Fred 当我第二次启动脚本时,它会按照预期的方式工作。它给出错误消息并且不启动该过程。我不明白您的第二部分,但我所说的 kill $$ 的意思是,我使用命令“ps -ef”手动搜索 PID,然后将其杀死。感谢您的建议,我将在我的源代码中进行更改。我必须说我从另一个论坛帖子中复制了带有 PID 文件的第一部分,但其余部分仍然相当困难,因为我没有在这个示例中添加更多操作!
-
当您写“bash 脚本正在运行 bash 脚本的第二个实例”时,您的意思是您提供代码的 bash 脚本正在调用自身吗?还是您的意思是第一个脚本调用了第二个脚本(可能是 PHP 脚本)两次?
-
我的意思是它以某种方式自称。这里 ps -ef 的两个条目: 1. root 1439 1433 0 11:19 pts/0 00:00:00 /bin/bash /.../my_script 2. root 3488 1439 0 15:10 pts/0 00:00 :00 /bin/bash /.../my_script
标签: php bash shell pid inotify