Как получить путь к процессу в Unix / Linux

в среде Windows существует API для получения пути, по которому выполняется процесс. Есть ли что-то подобное в Unix / Linux?

или есть какой другой способ сделать это в подобных условиях?

10 ответов


в Linux, символьная ссылка /proc/<pid>/exe имеет путь к исполняемому файлу. Используйте команду readlink -f /proc/<pid>/exe чтобы получить значение.

в AIX, этот файл не существует. Вы могли бы сравнить cksum <actual path to binary> и cksum /proc/<pid>/object/a.out.


вы можете легко найти exe этими способами, просто попробуйте сами.

  • ll /proc/<PID>/exe
  • pwdx <PID>
  • lsof -p <PID> | grep cwd

немного поздно, но все ответы были специфичны для 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 */
    size_t buff_len;
    if (buff_len = readlink ("/proc/self/exe", path, dest_len - 1) != -1)
    {
        path [buff_len] = '';
        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;
}

редактировать: Исправлена ошибка, о которой сообщил Марк лаката.


Я использую:

ps -ef | grep 786

замените 786 своим PID или именем процесса.


в Linux каждый процесс имеет свою собственную папку в /proc. Так что вы могли бы использовать getpid() чтобы получить pid запущенного процесса, а затем присоединиться к нему с помощью path /proc чтобы получить папку, которую вы, надеюсь, нужна.

вот краткий пример в 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 

pwdx <process id>

эта команда будет извлекать путь процесса из того места, где он выполняется.


нет метода "гарантированно работать в любом месте".

Шаг 1-проверить argv[0], если программа была запущена по полному пути, это (обычно) будет иметь полный путь. Если он был запущен относительным путем, то же самое выполняется (хотя для этого требуется получить текущий рабочий каталог, используя getcwd().

Шаг 2, Если ни один из вышеперечисленных не выполняется, должен получить имя программы, а затем получить имя программы из argv[0], а затем получить путь пользователя из окружающая среда и пройти через это, чтобы увидеть, если есть любой исполняемый файл с тем же именем.

обратите внимание, что argv[0] устанавливается процессом, который выполняет программу, поэтому он не является 100% надежным.


спасибо : Kiwy
с AIX:

getPathByPid()
{
    if [[ -e /proc//object/a.out ]]; then
        inode=`ls -i /proc//object/a.out 2>/dev/null | awk '{print }'`
        if [[ $? -eq 0 ]]; then
            strnode=${inode}"$"
            strNum=`ls -li /proc//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 }'`
                n2=`echo $strNum|awk -F"." '{print }'`
                # 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
}

вы также можете получить путь на GNU / Linux с (не полностью протестирован):

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, '/') = '';
/*chdir(buf);*/

найти путь к имени процесса

#!/bin/bash
# @author Lukas Gottschall
PID=`ps aux | grep precessname | grep -v grep | awk '{ print  }'`
PATH=`ls -ald --color=never /proc/$PID/exe | awk '{ print  }'`
echo $PATH