如何在Unix / Linux中获得进程的path
在Windows环境中,有一个API来获取正在运行进程的path。 在Unix / Linux中有类似的东西吗?
或者在这些环境中还有其他方法可以做到这一点吗?
在Linux上,符号链接/proc/<pid>/exe
具有可执行文件的path。 使用命令readlink -f /proc/<pid>/exe
来获取值。
在AIX上,这个文件不存在。 你可以比较cksum <actual path to binary>
和cksum /proc/<pid>/object/a.out
。
编辑注意 下面的代码有一个错误。 readlink
不会终止输出string,所以如果它工作,这是一个意外。
有点晚,但所有的答案是特定于Linux。
如果你还需要unix,那么你需要这个:
char * getExecPath (char * path,size_t dest_len, char * argv0) { char * baseName = NULL; char * systemPath = NULL; char * candidateDir = NULL; /* the easiest case: we are in linux */ if (readlink ("/proc/self/exe", path, dest_len) != -1) { dirname (path); strcat (path, "/"); return path; } /* Ups... not in linux, no guarantee */ /* check if we have something like execve("foobar", NULL, NULL) */ if (argv0 == NULL) { /* we surrender and give current path instead */ if (getcwd (path, dest_len) == NULL) return NULL; strcat (path, "/"); return path; } /* argv[0] */ /* if dest_len < PATH_MAX may cause buffer overflow */ if ((realpath (argv0, path)) && (!access (path, F_OK))) { dirname (path); strcat (path, "/"); return path; } /* Current path */ baseName = basename (argv0); if (getcwd (path, dest_len - strlen (baseName) - 1) == NULL) return NULL; strcat (path, "/"); strcat (path, baseName); if (access (path, F_OK) == 0) { dirname (path); strcat (path, "/"); return path; } /* Try the PATH. */ systemPath = getenv ("PATH"); if (systemPath != NULL) { dest_len--; systemPath = strdup (systemPath); for (candidateDir = strtok (systemPath, ":"); candidateDir != NULL; candidateDir = strtok (NULL, ":")) { strncpy (path, candidateDir, dest_len); strncat (path, "/", dest_len); strncat (path, baseName, dest_len); if (access(path, F_OK) == 0) { free (systemPath); dirname (path); strcat (path, "/"); return path; } } free(systemPath); dest_len++; } /* again someone has use execve: we dont knowe the executable name; we surrender and give instead current path */ if (getcwd (path, dest_len - 1) == NULL) return NULL; strcat (path, "/"); return path; }
你可以通过这些方式轻松findexe,只需自己试一试。
-
ll /proc/<PID>/exe
-
pwdx <PID>
-
lsof -p <PID> | grep cwd
我用:
ps -ef | grep 786
将786replace为您的PID或进程名称。
在Linux中,每个进程在/proc
中都有自己的文件夹。 所以你可以使用getpid()
来获得正在运行的进程的pid,然后用path/proc
join到你想要的文件夹中。
这是Python中的一个简短例子:
import os print os.path.join('/proc', str(os.getpid()))
以下是ANSI C中的示例:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> int main(int argc, char **argv) { pid_t pid = getpid(); fprintf(stdout, "Path to current process: '/proc/%d/'\n", (int)pid); return EXIT_SUCCESS; }
编译它:
gcc -Wall -Werror -g -ansi -pedantic process_path.c -oprocess_path
没有“保证在任何地方工作”的方法。
第一步是检查argv [0],如果程序是以其完整path启动的,那么(通常)会有完整的path。 如果它是由相对path启动的,则同样适用(尽pipe这需要使用getcwd()来获取当前工作目录。
步骤2,如果以上都不成立,就是得到程序的名字,然后从argv [0]得到程序的名字,然后从环境中获得用户的PATH,并通过它来查看是否有合适的可执行二进制具有相同的名称。
请注意,argv [0]是由执行程序的进程设置的,因此它不是100%可靠的。
你也可以在GNU / Linux上findpath(未经彻底testing):
char file[32]; char buf[64]; pid_t pid = getpid(); sprintf(file, "/proc/%i/cmdline", pid); FILE *f = fopen(file, "r"); fgets(buf, 64, f); fclose(f);
如果你想让可执行文件的目录改变工作目录到进程的目录(对于media / data / etc),你需要在最后一个/
*strrchr(buf, '/') = '\0'; /*chdir(buf);*/
感谢: 奇维
与AIX:
getPathByPid() { if [[ -e /proc/$1/object/a.out ]]; then inode=`ls -i /proc/$1/object/a.out 2>/dev/null | awk '{print $1}'` if [[ $? -eq 0 ]]; then strnode=${inode}"$" strNum=`ls -li /proc/$1/object/ 2>/dev/null | grep $strnode | awk '{print $NF}' | grep "[0-9]\{1,\}\.[0-9]\{1,\}\."` if [[ $? -eq 0 ]]; then # jfs2.10.6.5869 n1=`echo $strNum|awk -F"." '{print $2}'` n2=`echo $strNum|awk -F"." '{print $3}'` # brw-rw---- 1 root system 10, 6 Aug 23 2013 hd9var strexp="^b.*"$n1,"[[:space:]]\{1,\}"$n2"[[:space:]]\{1,\}.*$" # "^b.*10, \{1,\}5 \{1,\}.*$" strdf=`ls -l /dev/ | grep $strexp | awk '{print $NF}'` if [[ $? -eq 0 ]]; then strMpath=`df | grep $strdf | awk '{print $NF}'` if [[ $? -eq 0 ]]; then find $strMpath -inum $inode 2>/dev/null if [[ $? -eq 0 ]]; then return 0 fi fi fi fi fi fi return 1 }
find进程名称的path
#!/bin/bash # @author Lukas Gottschall PID=`ps aux | grep precessname | grep -v grep | awk '{ print $2 }'` PATH=`ls -ald --color=never /proc/$PID/exe | awk '{ print $10 }'` echo $PATH