jobs
调用每个作业时的输出包含工作目录(不一定是每个作业的当前工作目录)是否正确?
$ jobs -l | grep JDBC
[15] 20422 Running PDFXCview all.pdf & (wd: ~/mydata/dirlinks/cs/SQL/API/JDBC/general/official/tutorials)
[20] 20542 Running PDFXCview all.pdf & (wd: ~/mydata/dirlinks/cs/SQL/API/JDBC/general/wikipedia)
类似地,在中ps
,是否可以在调用每个进程时获取其上一个工作目录
在 中pgrep
,调用时是否可以在每个进程的前一个工作目录的路径名(字符串)中搜索pgrep ... <pattern_in_working_dir_pathname>
?
我想在调用进程时通过工作目录中的关键字搜索进程
谢谢。
答案1
命令jobs
可能显示程序的工作目录开始了中,如果该目录与 shell 的当前目录不同。这是因为 shell 正在跟踪它所知道的内容(进程开始的位置),而不是当前状态。
它还依赖于外壳。
例如与bash
bash-4.4$ cd /tmp
bash-4.4$ sleep 1000 &
[1] 24807
bash-4.4$ jobs -l
[1]+ 24807 Running sleep 1000 &
bash-4.4$ cd /
bash-4.4$ jobs -l
[1]+ 24807 Running sleep 1000 & (wd: /tmp)
但ksh93
不这样做
$ sleep 1000 &
[1] 7164
$ jobs -l
[1] + 7164 Running sleep 1000 &
$ cd /
$ jobs -l
[1] + 7164 Running sleep 1000 &
$
我不相信有任何可移植的方法来查找进程的 cwd。 fstat
,pwdx
类似的可能会有所帮助。您可能需要root
权限才能查看不属于您的进程。
在 Linux 上,可以通过查看符号链接来使用与特定路径匹配的进程/proc/.../cwd
:
例如,查找/tmp
路径中的进程:
% sudo ls -l /proc/*/cwd | grep /tmp
lrwxrwxrwx. 1 sweh sweh 0 Jul 28 09:38 /proc/23435/cwd -> /news/tmp
lrwxrwxrwx. 1 sweh sweh 0 Jul 28 09:39 /proc/7124/cwd -> /news/tmp
请记住,由于符号链接,这可能与进程的目录内部表示不匹配:
$ cd /usr/tmp
$ pwd
/usr/tmp
$ ls -l /proc/self/cwd
lrwxrwxrwx. 1 sweh sweh 0 Jul 28 09:41 /proc/self/cwd -> /var/tmp/
$ ls -l /usr/tmp
lrwxrwxrwx 1 root root 10 May 13 09:39 /usr/tmp -> ../var/tmp/
$
外壳认为我在里面,/usr/tmp
但实际上它在里面/var/tmp
。
编辑添加:
此问题有一个特殊情况,其中问题可能是“哪些进程正在使用安装点”。这不是报告cwd
任何可能打开的文件。
因此,例如:
$ sudo fuser -u -c /brick
/brick: 3552(root)
$ ps -p 3552
PID TTY TIME CMD
3552 ? 00:04:51 glusterfsd
$
我们知道该glusterfsd
进程是唯一使用/brick
文件系统的进程
答案2
没有一种可移植的方法来执行此操作ps
,但您可以使用 for 循环来ps
打印所有进程,然后将其通过管道传输到另一个命令来打印其当前工作目录。
让我们从pwdx
专门打印进程的当前工作目录开始。
以 root 身份运行:
for i in $(ps aux | awk '{print $2}'); do pwdx $i; done
ps aux | awk '{print $2}'
打印每个进程的 pid。
pwdx $i
将 pid 的 i 变量传递给pwdx
您可以pwdx
在 pid 本身上使用,但 for 循环将它们一起执行。
您也可以使用,但根据您的系统,lsof
您可能需要先安装该软件包。lsof
以 root 身份运行:
for i in $(ps aux | awk '{print $2}'); do lsof -p $i | grep cwd; done
ps aux | awk '{print $2}'
打印每个进程的 PID。
lsof -p $i
将 i 变量传递给lsof
grep cwd
cwd
打印包含当前工作目录的行。
关于pgrep
命令,您可以使用以下形式:
pgrep <process-name>
为了也找到进程的 pid,但您仍然必须将其传递给lsof
或pwdx
来查找当前工作目录。
第一个for loop
适用于 Fedora 28、Centos 7.5、RHEL 7.5 和 Debian 9,但不适用于 FreeBSD 11。
第二个for loop
适用于 Fedora 28、Centos 7.5、RHEL 7.5 和 Debian 9。它也适用于 FreeBSD 11.1,尽管在我的例子中,它打印出有关lsof
FreeBSD 11 版本的警告消息,而我的是 FreeBSD 11.1
答案3
许多操作系统中的其他进程都知道进程的工作目录。在 BSD 和 Linux 上,可以分别使用sysctl()
和从内核中查询它们procfs
。然而,Linux 都没有ps
但是, procps 中的ps
命令和BSD 中的命令都不会获取并报告此信息。
要获取 BSD 上进程的当前目录,命令是fstat
,它报告文件系统和 i 节点号。
% fstat -p $$|awk '{ if ("wd" == $4 || 1 == NR) 打印; }' 用户命令 PID FD 安装 INUM 模式 SZ|DV R/W JdeBP zsh 71512 wd /usr/home/JdeBP 4 drwxr-xr-x 127 r %
请注意,当然,工作目录可以通过多个名称访问,并且这些名称可能会随着内容的重命名和链接的创建/销毁而变化。其中稳定的部分是文件对象、vnode,而不是用于到达它的目录条目。
因此,在 中报告一个名称的 Linux 机制并不一定可靠。/proc/pid/cwd
最后:请注意当前的进程的目录不一定是进程生成时的工作目录,这是所有作业控制 shell实际上知道。