抱歉,这张彩色屏幕截图比复制粘贴 + 代码格式更能突出问题:
以下是代码格式的同一屏幕:
───────────────────────────────────────────────────────────────────────────────
rick@dell:~$ ps a | grep display-
26457 pts/2 S+ 0:00 grep --color=auto display-
───────────────────────────────────────────────────────────────────────────────
rick@dell:~$ ps a | grep display-
28927 pts/18 S+ 0:00 sudo /usr/local/bin/display-auto-brightness
29174 pts/18 S+ 0:00 /bin/bash /usr/local/bin/display-auto-brightness
30183 pts/2 S+ 0:00 grep --color=auto display-
───────────────────────────────────────────────────────────────────────────────
rick@dell:~$ pstree | grep display-
|-cron---cron---sh---display-auto-br---sleep
| | | | |-bash---sudo---display-auto-br---sleep
───────────────────────────────────────────────────────────────────────────────
rick@dell:~$ ps a | grep cron
16031 pts/2 S+ 0:00 grep --color=auto cron
───────────────────────────────────────────────────────────────────────────────
rick@dell:~$ ps a | grep display
26773 pts/2 S+ 0:00 grep --color=auto display
28927 pts/18 S+ 0:00 sudo /usr/local/bin/display-auto-brightness
29174 pts/18 S+ 0:00 /bin/bash /usr/local/bin/display-auto-brightness
───────────────────────────────────────────────────────────────────────────────
今天早上重启后,cron 作业/etc/cron.d/display-auto-brightness
应该已经启动了。根据第一部分,我认为它从未启动过。
我使用 手动启动了脚本sudo /usr/local/bin/display-auto-brightness
。第二部分显示了如何ps
为单个作业返回两个进程 ID。一个用于sudo
启动作业的海拔,另一个用于脚本本身。
是否有一种编程方式可以将这两个 PID 识别为一个作业?原因是,下一个开发步骤是从挂起状态恢复时,查看单个作业(而不是两个进程)是否已在运行,并在再次启动同一作业时将其终止。如果在黑暗中挂起后在白天恢复,这将立即调整显示亮度,反之亦然。
在第三部分中,我使用了该pstree
命令,发现命令中未出现的 cron 作业ps
显示在这里。这是为什么?。
在第四部分中,我通过使用过滤器来管道ps
输出,但什么也没有显示。grep
cron
这是为什么?
在第五部分也是最后一部分,我重复了第二部分ps a | grep display-
以重申先前的发现。
编辑1
我想我已经弄清楚为什么第四部分没有显示cron
正在运行。这是因为 cron 以 root 身份运行时处于正常用户状态。解决方案是使用:
$ sudo ps aux | grep cron
root 1122 0.0 0.0 29008 2936 ? Ss 04:16 0:00 /usr/sbin/cron -f
rick 7273 0.0 0.0 14224 1028 pts/2 S+ 17:50 0:00 grep --color=auto cron
现在我们可以看到,原来在凌晨 4:16 重启的进程仍在 cron 任务下运行。进程 ID1122display-auto-brightness
可能是将来程序更改时从暂停状态恢复时需要终止的程序。这仍然与命令找到的脚本名称无关pstree
。
编辑 2 Windows Subsystem for Linux 桌面快捷方式
当设置一个图标从 Windows 10 桌面调用 bash 脚本时,你会获得比普通 Ubuntu 16.04 和 Unity 下更多的运行程序:
$ ps -ef | grep lock-screen
rick 29243 29242 0 17:13 tty1 00:00:00 /bin/bash -c cd && DISPLAY=0:0 /mnt/e/bin/lock-screen-timer
rick 29244 29243 0 17:13 tty1 00:00:00 /bin/bash /mnt/e/bin/lock-screen-timer
当您使用时,pstree
会有更多 PID:
$ pstree -gp | grep lock-screen
|-init(29242,29242)---bash(29243,29242)---lock-screen-tim(29244,29242)---sleep(29777,29242)
在“旧”方法中,我会杀死lock-screen-timer
“29244”。 看看我认为我应该杀死“29243”。但ps -aux
看看父进程应该被杀死,即“29242”。pstree
init
进一步的测试表明你无法消除init
PID
此屏幕截图显示了您无法init
直接杀死 PID。您可以杀死它的子进程,这会导致它死亡,但孙子进程和曾孙进程仍在运行。当使用桌面快捷方式时,您似乎需要在 Windows 10 WSL 下杀死三个 PID:
rick@alien:/mnt/c/Windows/System32$ pstree -gp | grep lock-screen
|-init(30554,30554)---bash(30555,30554)---lock-screen-tim(30556,30554)---sleep(30587,30554)
rick@alien:/mnt/c/Windows/System32$ kill 30554
-bash: kill: (30554) - Operation not permitted
rick@alien:/mnt/c/Windows/System32$ sudo kill 30554
[sudo] password for rick:
rick@alien:/mnt/c/Windows/System32$ pstree -gp | grep lock-screen
|-init(30554,30554)---bash(30555,30554)---lock-screen-tim(30556,30554)---sleep(30587,30554)
rick@alien:/mnt/c/Windows/System32$ kill 30555
rick@alien:/mnt/c/Windows/System32$ pstree -gp | grep lock-screen
|-lock-screen-tim(30556,30554)---sleep(30612,30554)
rick@alien:/mnt/c/Windows/System32$ pstree -gp | grep sleep
|-lock-screen-tim(30556,30554)---sleep(30633,30554)
rick@alien:/mnt/c/Windows/System32$ kill 30556
rick@alien:/mnt/c/Windows/System32$ pstree -gp | grep sleep
`-sleep(30633,30554)
rick@alien:/mnt/c/Windows/System32$ kill 30633
答案1
实际上是的,有一种方法可以将它们识别为单个进程,但有一个条件。
假设我们有这个:
#!/bin/bash
loop_function(){
while :
do
sleep 3
done
}
loop_function &
while true
do
sleep 3
done
我们在后台启动它:
bash-4.3$ ./simple_example.sh &
[1] 16180
这里我们看到脚本本身的 PID 为 16180。它的所有子进程都有不同的 PID。现在,它们都有共同的父进程:#!
行中指定的 shell,即我们在后台执行脚本时报告的完全相同的 PID。因此,通过使用ps
指定ppid
,我们可以搜索属于同一进程的所有进程。
bash-4.3$ ps -e -o ppid,command | grep 16180 | grep -v grep
16180 /bin/bash ./simple_example.sh
16180 sleep 3
现在,显然,这意味着两件事:
- 要将进程分组,您必须知道父 PID
- 子进程的子进程将具有不同的父进程 PID,因此如果您有多个级别的函数调用,则很难跟踪所有进程。
至于pstree
问题的一部分,该作业确实出现在那里 - 它只是被切断了grep
。您也不需要sudo
查看 cronjobs:
$ ps -ef | grep cron | grep -v grep && echo $USER
root 896 1 0 09:47 ? 00:00:00 /usr/sbin/cron -f
xieerqi
答案2
由于您只想查找正在运行的进程的 PID,而不是任何间接关联的内容(即调用的 PIDsudo
和grep
对进程名称的搜索),因此您可以从初始搜索中 grep 出有问题的单词。
$ ps aux | grep display-auto-brightness | grep -vw -e grep -e sudo | awk '{print $2}'
答案3
感谢这个问答(如果 cron 作业未在 ps 中显示,该如何终止它?或者让它在 ps 中显示?)我走上了正确的道路:
───────────────────────────────────────────────────────────────────────────────
rick@dell:~$ ps wwuxa |grep display-auto | grep -v grep
root 1584 0.0 0.0 4508 780 ? Ss 14:02 0:00 /bin/sh -c /usr/local/bin/display-auto-brightness
root 1592 0.0 0.0 12564 2984 ? S 14:02 0:00 /bin/bash /usr/local/bin/display-auto-brightness
───────────────────────────────────────────────────────────────────────────────
rick@dell:~$ pstree -p -g | grep display-auto
|-cron(1376,1376)---cron(1436,1376)---sh(1584,1584)---display-auto-br(1592,1584)---sleep(16989,1584)
───────────────────────────────────────────────────────────────────────────────
rick@dell:~$
杀死 cron(pid 为 1376 和 1436)可能不是一个好主意。但是杀死 bash shell(1584),它是显示自动亮度(1592)睡觉(16989)应该终止子进程和孙进程。这样,子进程(display-auto-brightness)的两个副本就不会同时运行。
现在面临的挑战是编写脚本,但至少现在我知道如何提取信息。