Как мне получить путь к процессу в Unix / Linux - PullRequest
118 голосов
/ 03 марта 2009

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

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

Ответы [ 11 ]

160 голосов
/ 03 марта 2009

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

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

51 голосов
/ 01 июля 2014

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

  • ll /proc/<PID>/exe
  • pwdx <PID>
  • lsof -p <PID> | grep cwd
27 голосов
/ 09 марта 2009

Немного поздно, но все ответы были специфичны для 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] = '\0';
        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;
}

РЕДАКТИРОВАНИЕ: Исправлена ​​ошибка, о которой сообщил Марк Лаката.

11 голосов
/ 02 августа 2014

Я использую:

ps -ef | grep 786

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

6 голосов
/ 22 декабря 2017

pwdx <process id>

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

4 голосов
/ 03 марта 2009

В Linux каждый процесс имеет свою собственную папку в /proc. Таким образом, вы можете использовать getpid(), чтобы получить pid запущенного процесса, а затем соединить его с путем /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 
2 голосов
/ 11 августа 2015

спасибо: Kiwy
с 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
}
2 голосов
/ 03 марта 2009

Нет метода "гарантированно где-то работать".

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

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

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

1 голос
/ 25 января 2019

Приведенная ниже команда выполняет поиск имени процесса в списке запущенных процессов и перенаправляет команду pid на pwdx, чтобы найти местоположение процесса.

ps -ef | grep "abc" |grep -v grep| awk '{print $2}' | xargs pwdx

Замените "abc" вашим конкретным шаблоном.

В качестве альтернативы, если вы можете настроить ее как функцию в .bashrc, вам может пригодиться ее использование, если вам нужно ее часто использовать.

ps1() { ps -ef | grep "$1" |grep -v grep| awk '{print $2}' | xargs pwdx; }

Например:

[admin@myserver:/home2/Avro/AvroGen]$ ps1 nifi

18404: /home2/Avro/NIFI

Надеюсь, это когда-нибудь кому-нибудь поможет .....

1 голос
/ 12 мая 2012

Вы также можете получить путь в 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);

Если вы хотите, чтобы каталог исполняемого файла, возможно, изменил рабочий каталог на каталог процесса (для носителя / данных / и т. Д.), Вам нужно удалить все после последнего /:

*strrchr(buf, '/') = '\0';
/*chdir(buf);*/
...