什么是.pid文件?

评论 0 浏览 0 2020-09-24

1.概述

有时有必要保存Linux进程的进程识别号(PID)。在本教程中,我们将介绍一种使用.pid文件来存储PID的常见方法,并举例说明如何使用它。

2.什么是.pid文件?

有时,应用程序会将PID写到一个文件中,以方便访问。它只是一个只包含进程的PID的文本文件。在创建或使用方面没有特定的规则。它只是一个有用的惯例。

让我们先来看看创建.pid文件的一个简短的例子。

3.创建a .pid文件

现在让我们来讨论一下.pid文件的创建。

3.1.初始文件创建

我们在脚本中创建.pid文件的一种方法是将$$的输出通过管道传输到文件中:

% echo $$ > myShell.pid
% cat myShell.pid
40276

$$是一个Linux变量,用于返回它被调用的进程的PID。在这个例子中,它是shell的PID。

现在,让我们从一个小的脚本开始。

#!/bin/bash
  
# create file
pid_file="process.pid"
echo $$ > $pid_file

count=0
while [ $count -le 10 ]
do
  echo Going $count..
  sleep 1
  count=$(($count+1))
done

当我们运行该脚本时。

% ./process.sh

我们将看到两件事。首先,我们将看到这个过程的输出。

% ./process.sh
Going 0..
Going 1..
Going 2..
Going 3..
Going 4..
Going 5..
Going 6..
Going 7..
Going 8..
Going 9..
Going 10..

如果我们在另一个终端窗口中运行ls,我们会看到process.pid文件。

% ls
process.pid	process.sh

它包含运行该脚本的进程的PID。我们可以通过在文件上使用cat来验证这一点。

% cat process.pid
34876

3.2 .pid文件的位置

虽然我们可以把.pid文件放在任何地方,但通常,我们会让我们的进程把文件放在/var/run。为了避免与其他进程发生冲突,我们可以更进一步,创建一个新的目录,/var/run/myScript

% echo $$ > /var/run/myScript/myShell.pid

然而,在某些系统中,这个目录可能被root所拥有,在这种情况下,我们可能无法在那里写入我们的.pid文件。第二个选择是主目录。

% $$ > ~/myScript/myShell.pid

4.使用.pid文件杀死一个进程

现在我们有了一个.pid文件用于我们的进程,让我们考虑一下我们可以用它做什么。

假设我们想在进程运行时终止它。如果有 .pid 文件,我们可以从文件中获取 PID,然后将其与 xargskill 一起使用。这确保我们只需要知道 .pid 文件的名称和位置,而不是实际的 PID 本身:

% cat process.pid | xargs kill

这里的主要好处是,我们正是在杀死我们想要杀死的进程。我们可以做这样的事情。

ps -ef | grep process

但是,如果该应用程序有多个实例在运行,这样做可能会出现多个结果。例如,它还会显示实际运行grep的进程。

% ps -ef | grep process
  501 40311 40276   0  7:00AM ttys001    0:00.00 grep process

在这种情况下,我们将不得不在杀死任何东西之前考虑到意外的匹配情况。

5.确保一个应用程序的单一实例

我们也可以使用.pid文件来确保一个应用程序在我们启动它之前没有运行。要做到这一点,我们的脚本需要做两个改动。首先,我们需要在运行结束时删除.pid文件。

# clean up file after we're done
rm $pid_file

第二,我们需要在开头添加一个检查,以确定是否存在一个.pid文件。

if [ ! -f $pid_file ]; then
  echo "Creating .pid file $pid_file"
  echo $$ > $pid_file
else
  echo "Found .pid file named $pid_file. Instance of application already exists. Exiting."
  exit
fi

如果该文件存在,我们将假定该应用程序正在运行,并退出而不运行脚本的其余部分。

所以现在,我们的脚本看起来像这样。

#!/bin/bash
  
# create file
pid_file="process.pid"

if [ -f $pid_file ]; then
  echo "Found existing .pid file named $pid_file. Exiting."
  exit
else
  echo "Creating .pid file $pid_file"
  echo $$ > $pid_file
fi

count=0
while [ $count -le 10 ]
do
  echo Going $count..
  sleep 1
  count=$(($count+1))
done

# clean up file after we're done
rm $pid_file

让我们打开两个终端窗口,在两个窗口中运行我们的脚本,看看它的实际效果。

% ./process.sh

第一个窗口将按预期的方式运行。

% ./process.sh 
Creating .pid file process.pid
Going 0..
Going 1..
Going 2..

而第二个窗口将检测到.pid文件,并在不运行的情况下退出。

% ./process.sh 
Found existing .pid file named process.pid. Exiting.

6.处理过时的.pid文件

在这种实现方式下,我们可能会遇到的一个问题是.pid文件过期。假设应用程序在没有达到清理我们的.pid文件的那一行就死亡了。如果我们重新启动应用程序,该文件将仍然存在,并且脚本将退出而不运行。

我们可以扩展我们的启动检查来处理这种情况。我们可以确保,如果.pid文件存在,里面的PID也是一个有效的进程。让我们试着用pgrep来检查.pid文件的内容。

pgrep -F process.pid

如果有进程与PID相匹配,这将返回0的退出代码;如果没有与PID相匹配的进程,则返回1。

所以现在,我们的脚本将在开始时进行两项检查:

#!/bin/bash
  
# create file
pid_file="process.pid"

if [ -f $pid_file ]; then
  echo "Found existing .pid file named $pid_file. Checking."

  # check the pid to see if the process exists
  pgrep -F $pid_file
  pid_is_stale=$?
  old_pid=$( cat $pid_file )
  echo "pgrep check on existing .pid file returned exit status: $pid_is_stale"

  if [ $pid_is_stale -eq 1 ]; then
    echo "PID $old_pid is stale. Removing file and continuing."
    rm $pid_file
  else 
    echo "PID $old_pid is still running or pgrep check errored. Exiting."
    exit
  fi
else 
  echo "Creating .pid file $pid_file"
  echo $$ > $pid_file
fi

count=0
while [ $count -le 10 ]
do
  echo Going $count..
  sleep 1
  count=$(($count+1))
done

# clean up file after we're done
rm $pid_file

要看到“陈旧文件”的逻辑工作,在命令行启动应用程序,并立即用CTRL+c杀死它。这将产生并留下一个陈旧的.pid文件。再次启动该脚本,我们会看到。

./process.sh
Found existing .pid file named process.pid. Checking.
pgrep check on existing .pid file returned exit status: 1
PID 35975 is stale. Removing file and continuing.
Going 0..
Going 1..

我们可以通过在一个窗口中启动应用程序,然后在另一个窗口中立即启动它来看到“仍在运行”的逻辑。我们将在第二个窗口中看到这一点。

% ./process.sh
Found existing .pid file named process.pid. Checking.
35926
pgrep check on existing .pid file returned exit status: 0
PID 35926 is still running or pgrep check errored. Exiting.

所以现在,我们有一个脚本,使用.pid文件,以确保我们一次只运行一个应用程序的实例。

7.结语

在这篇文章中,我们学习了使用.pid文件来跟踪进程的PID

最后更新2022-11-17
0 个评论
标签
ps