我有一个在 RedHat Linux 实例上运行的 Java 进程。
问题是我杀了它之后它又会重新出现。我不知道该去哪里寻找。我已经去了 crontab,但没有运气。
我查看了 PPID,但它指向 init (1)。
知道如何找到来源吗?
答案1
有多种可能性(其他答案中提到了一些可能性):
- 经常执行的系统或用户 cronjob,
- 在 SysV init 中,带有指令
/etc/inittab
的服务条目respawn
, - 在 systemd 中,单元文件的
Restart
选项设置为除 之外的值no
, - 在 Upstart 中,带有指令的服务配置文件
respawn
, - 过程监控工具,例如
monit
, 或者 - 该特定服务的临时看门狗进程。
一个有趣的新工具(仅限 Linux)可以提供更多关于进程启动位置的信息:系统挖掘。
Sysdig 使用 Linux 内核的跟踪点功能来提供快速、系统范围的strace
.
例如,如果我想看到每个进程都在启动ls
,我可以发出:
sudo sysdig evt.type=execve and evt.arg.exe=ls
当ls
在某处运行时,我会收到如下消息:
245490 16:53:54.090856066 3 ls (10053) < execve res=0 exe=ls args=--color=auto. tid=10053(ls) pid=10053(ls) ptid=9204(bash) cwd=/home/steved fdlimit=1024 pgft_maj=0 pgft_min=37 vm_size=412 vm_rss=4 vm_swap=0 env=...
我截断了返回的环境信息,但是正如你所看到的,在 ptid 中我可以看到调用 execve 的程序的名称和 pid。 execve
是 Linux 中用于执行新命令的系统调用(所有其他 exec 调用只是 execve 的前端)。
答案2
我相信你可以用pstree
。您可以将命令指定为,
pstree -p PID
上面将为您提供 java 应用程序的所有父级的列表。
答案3
您可以查看其 PPID(父进程 ID):
$ ps -eo pid,ppid,args | grep java
获得 Java 进程的 PPID(第二列)后,ps
再次使用它来查找关联的进程:
$ ps -p [PPID]
编辑:如果父级为 1(init),则第一的你的Java进程的父进程在“分娩”后就死了(多么悲伤)。因此,您无法使用当前的进程层次结构来查找它。我建议您做的第一件事就是检查ps -ef
。您只需阅读输出就可以找到罪魁祸首。
然后,看看 crontab(你已经这么做了,但不会有什么坏处):
$ for user in $(cut -f1 -d: /etc/passwd); do echo $user; crontab -u $user -l; done
这将需要 root 权限。
仍然看不到已安排的 Java 进程?该死的。让我们尝试一些别的东西。如果您的 Java 进程自启动后就存在,请查看启动时安排的程序。我会建议像...
$ grep -iR java /etc/rc*
如果你仍然找不到任何东西,那么......好吧,我承认我已经没有主意了。您确实应该再看一下ps -ef
并找到与基于 Java 的程序关联的进程。您应该会遇到一个守护进程,或者一个“启动器”,负责不断重生您的 Java 进程。
答案4
如果您不知道谁是父母,您应该使用一些系统跟踪器,例如审计
您可以使用以下命令启用日志记录:
auditctl -a exit,always -S execve -F path=/usr/bin/rrdtool
然后/var/log/audit/audit.log
找到如下行:
type=SYSCALL msg=audit(1414027338.620:6232): arch=c000003e syscall=59
success=yes exit=0 a0=7fdea0e4db23 a1=7fffec7c5220 a2=7fffec7c87d0
a3=7fdea1b559d0 items=2 ppid=17176 pid=18182 auid=1000 uid=1000 gid=1000
euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=pts8
ses=2 comm="sh" exe="/bin/dash" key=(null)
(为了便于阅读分成多行)。您感兴趣exe="/bin/dash"
和/或pid=18182
哪个标识您想要查找的胭脂进程,以及ppid=17176
哪个标识执行它的父进程。