Как узнать путь к процессу в Unix / Linux

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

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


person lsalamon    schedule 03.03.2009    source источник


Ответы (11)


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

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

person jpalecek    schedule 03.03.2009
comment
sudo если вывод пустой, некоторые процессы созданы другими пользователями системы. - person Lun4i; 02.09.2017

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

  • ll /proc/<PID>/exe
  • pwdx <PID>
  • lsof -p <PID> | grep cwd
person hahakubile    schedule 01.07.2014
comment
Это круто. Я знал, что запустил его из места, где была символическая ссылка на исходный исполняемый файл (одна из многих версий). pwdx <PID> дал мне расположение символической ссылки, чтобы я мог найти журналы и остановить процесс должным образом. - person NurShomik; 12.04.2018
comment
ll обычно является псевдонимом: alias ll='ls -alF'. - person Pablo Bianchi; 21.08.2018
comment
Последние два (pwdx и lsof) могут дать неверный результат. Вопрос был о полном пути к исполняемому файлу. pwdx и lsof предоставят вам cwd процесса, а не путь к процессу. Я думаю, что ответ jpalecek более точен, поскольку исходный запросчик запрашивал путь к исполняемому файлу, а не программную ссылку, описывающую исполняемый файл. - person Shimon; 21.11.2019
comment
Это действительно полезно, однако для последнего, похоже, мне нужно использовать lsof -p <PID> | grep -m 1 txt, поскольку необходимая информация о пути процесса, похоже, находится в первой строке с txt, а не в строке cwd? (Применимо к macOS и Ubuntu на дату публикации.) - person MikeBeaton; 04.07.2021

Немного поздно, но все ответы были конкретно для 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;
}

EDITED: исправлена ​​ошибка, о которой сообщил Марк Лаката.

person Hiperion    schedule 09.03.2009
comment
Спасибо, что поделились Hiperion, но мне нужно было указать PID и получить его путь к exe, возможно ли это с помощью этого кода? - person Noitidart; 22.10.2016
comment
@Noitidart - заменить "/proc/self/exe" на sprintf(foo,"/proc/%d/exe",pid) - person Mark Lakata; 03.11.2016
comment
Обратите внимание, что readlink не завершает результат нулевым значением, поэтому этот код имеет неопределенное поведение. - person Mark Lakata; 04.11.2016

Я использую:

ps -ef | grep 786

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

person User    schedule 02.08.2014

pwdx <process id>

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

person gobi    schedule 22.12.2017
comment
Речь идет об API для получения информации, но все равно спасибо. - person lsalamon; 27.12.2017

В 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 
person hyperboreean    schedule 03.03.2009
comment
Вывод Python в последней версии Ubuntu: ››› import os ››› print os.path.join ('/ proc', str (os.getpid ())) / proc / 24346 - person Luke Stanley; 26.05.2012

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

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

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

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

person Vatine    schedule 03.03.2009

спасибо: 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
}
person zirong    schedule 11.08.2015

Приведенная ниже команда выполняет поиск имени процесса в списке запущенных процессов и перенаправляет 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

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

person Arun    schedule 25.01.2019

Вы также можете получить путь в 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, '/') = '\0';
/*chdir(buf);*/
person Jimmio92    schedule 12.05.2012

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

#!/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
person DwD    schedule 28.10.2011
comment
Пожалуйста, объясните свой код. Если вы скопировали и вставили его откуда-то еще, пожалуйста, дайте ссылку на источник. - person Tim; 08.11.2012
comment
Этот не очень эффективный код получает имя процесса (по сути, строка PID заменяет pgrep); в следующей строке он получает путь к исполняемому двоичному файлу (/proc/$PID/exe - символическая ссылка на исполняемый файл); и, наконец, он перекликается с этой символической ссылкой. - person Enrico; 19.07.2016