我不是系统管理员(我是软件开发人员),我有以下疑问。
执行此命令,我可以看到系统上运行的前 10 个进程的列表(如果我做错了,请纠正我):
[email protected] [~/FOLDER]# ps aux | head -10
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 191292 3892 ? Ss 2021 21:29 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
root 2 0.0 0.0 0 0 ? S 2021 0:00 [kthreadd]
root 4 0.0 0.0 0 0 ? S< 2021 0:00 [kworker/0:0H]
root 6 0.0 0.0 0 0 ? S 2021 2:17 [ksoftirqd/0]
root 7 0.0 0.0 0 0 ? S 2021 0:10 [migration/0]
root 8 0.0 0.0 0 0 ? S 2021 0:00 [rcu_bh]
root 9 0.1 0.0 0 0 ? S 2021 71:37 [rcu_sched]
root 10 0.0 0.0 0 0 ? S< 2021 0:00 [lru-add-drain]
root 11 0.0 0.0 0 0 ? S 2021 0:56 [watchdog/0]
所以第二列是PID识别进程(我可以用它来终止一个进程)。
然后我尝试执行此命令来检索与爪哇:
[email protected] [~/FOLDER]# ps aux | grep java
webadmin 22316 0.0 0.0 112812 980 pts/0 S+ 18:21 0:00 grep --color=auto java
基本上我只过滤与 java 相关的行
这里有一个疑问。PID始终是第二列的值吗?
是否可以像第一个代码片段中那样放置包含列名的标题?
答案1
简短的回答是你不需要使用ps aux
它。
通常这样的过程将运行为服务,以及服务管理器跟踪的它们的 PID(例如 systemd;Upstart;supervisord;Monit……)如果目标是检查服务是否正在运行 – 服务管理器可以回答这个问题。(例如,systemctl is-active MyApp
)如果目标是在服务崩溃时重新启动服务,或者防止服务运行两次 – 服务管理器的工作就是这样做。
在进程无法作为服务运行的情况下,应在启动时立即记录其 PID到 PID 文件– 应用程序本身或启动器都可以执行此操作。(例如,java -jar myapp.jar & echo $! > java.pid
。)
当您确实需要搜索所有正在运行的进程时,请使用该pgrep
命令。例如,要查找所有 Java 进程,请使用pgrep java
,要查找所有提及 MyApp.jar 的进程,请使用pgrep -f MyApp.jar
。(添加选项-a
以查看命令,例如pgrep -a java
。)这样就不会出现像 grep 那样返回其本身的问题ps|grep
。
如果你一定要使用ps
,那么指定确切的列您想要的。现在该u
选项已经要求特定的格式,特定的列以特定的顺序排列——但如果您想要的只是 PID,该o
选项只允许您获取 PID。例如,ps axo pid,cmd
总是会得到两列:PID 和命令,按该顺序排列。
答案2
仅查找 PIDpgrep
通常比 更好ps
。
现在我假设你知道你想要什么,你真正想要什么ps
,你想要标题。这个特定的任务可以用以下方法完成sed
:
ps aux | sed -n '1p; /java/p'
请注意,您ps … | grep …
可能会找到grep
本身。类似地,我的命令会找到sed
。您可以通过使用等同于java
但不包含 的正则表达式来避免这种情况java
。示例:
ps aux | sed -n '1p; /[j]ava/p'
如果您愿意grep
(例如因为它能够添加颜色),则以下方法似乎应该有效:
# flawed though, don't use it
ps aux | { head -n 1; grep '[j]ava'; }
它的缺陷在于head
可能会读取太多,并且没有办法将过度消耗的数据放回去以供grep
读取。read
在这方面更好,它一次读取一个字符,因此它可以可靠地读取一行:
ps aux | (IFS= read -r line; printf '%s\n' "$line"; grep '[j]ava')
注意,我强制使用子 shell,因此变量随之消亡,而主 shell 不受影响*。
* Shell 可以在不在子 Shell 中或隐式地在子 Shell 中运行管道的最后一部分。read line
不在子 Shell 中将line
在主 Shell 中设置变量。如果变量已经存在并且包含重要值怎么办?通过强制子 Shell,我们可以保护主 Shell 的状态,无论主 Shell 如何运行。