Як отримати шлях до процесу в Unix / Linux


138

У середовищі Windows існує API, щоб отримати шлях, по якому працює процес. Чи є щось подібне в Unix / Linux?

Або є якийсь інший спосіб зробити це в цих умовах?

Відповіді:


183

В Linux у симпосилання /proc/<pid>/exeє шлях до виконуваного файлу. Використовуйте команду, readlink -f /proc/<pid>/exeщоб отримати значення.

У AIX цей файл не існує. Можна порівняти cksum <actual path to binary>і cksum /proc/<pid>/object/a.out.


2
sudoякщо вихід порожній, деякі процеси створюються іншими користувачами системи.
Lun4i

63

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

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

1
Це круто. Я знав, що я запустив його з місця, яке мало символічне посилання на оригінальний виконуваний файл (одна з багатьох версій). pwdx <PID>дав мені розташування символічного посилання, щоб я міг знайти журнали та зупинити процес належним чином.
NurShomik

1
llзазвичай це псевдонім: alias ll='ls -alF'.
Пабло А

1
Останні два (pwdx та lsof) можуть не дати тобі правильного результату. Питання стосувалося повного шляху до виконуваного файлу. pwdx та lsof дадуть вам cwd процесу, а не шлях до цього процесу. Я думаю, що відповідь jpalecek є більш точною, оскільки оригінальний запитувач запитував шлях до виконуваного файлу, а не м'яке посилання, що описує виконуваний файл.
Шимон

28

Трохи пізно, але всі відповіді були специфічними для 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;
}

ВЕДЕНО: Виправлена ​​помилка, про яку повідомляв Марк lakata.


Дякую за те, що поділився Hiperion, але мені потрібно було вказати PID та отримати його exe шлях, чи можливо це за допомогою цього коду?
Noitidart

1
@Noitidart - замінити "/proc/self/exe"наsprintf(foo,"/proc/%d/exe",pid)
Марк Лаката

2
Зверніть увагу, що readlink не скасовує результат, тому цей код має невизначену поведінку.
Марк Лаката

Дякую @MarkLakata! :)
Noitidart

Дякуємо, що помітили @MarkLakata
Hiperion


11

pwdx <process id>

Ця команда отримає шлях процесу з того місця, де він виконується.


Питання в тому, щоб API отримати інформацію, але все одно дякую.
lsalamon

4

У 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 

Вихід Python на останній версії Ubuntu: >>> import os >>> print os.path.join ('/ proc', str (os.getpid ())) / proc / 24346
Люк Стенлі

3

Не існує методу "гарантованої роботи в будь-якому місці".

Крок 1 - це перевірити argv [0], якщо програма була запущена повним шляхом, це (як правило) матиме повний шлях. Якщо він був запущений відносним шляхом, той самий тримається (хоча для цього потрібно отримати поточну робочу директорію, використовуючи getcwd ().

Крок 2, якщо жодне з перерахованих вище не дотримується, полягає в тому, щоб отримати ім'я програми, а потім отримати ім'я програми з argv [0], потім отримати PATH користувача з оточення і перейти через це, щоб побачити, чи є підходящий виконуваний двійковий файл з однойменною назвою.

Зауважте, що argv [0] встановлюється процесом, який виконує програму, тому він не є 100% надійним.


2

спасибі: 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
}

Тільки що хтось зробив сценарій цього
Ківі

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);

Якщо ви хочете, щоб каталог виконуваного файлу, можливо, змінив робочий каталог у каталог каталогу (для медіа / даних / тощо), вам потрібно скинути все після останнього /:

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

1

Команда нижче знайде ім’я процесу у списку запущених процесів та перенаправить команду 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

Знайдіть шлях до назви процесу

#!/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

4
Поясніть, будь ласка, свій код. Якщо ви скопіювали та вставили його з іншого місця, будь ласка, посилання на джерело.
Тім

Що цей - не настільки ефективний - код - це отримання назви процесу (по суті, рядок "PID" є заміною для pgrep); у наступному рядку він отримує шлях виконуваного двійкового /proc/$PID/exeфайлу ( є символьним посиланням на виконуваний файл); і, нарешті, це перегукується із тим посиланнями.
Енріко
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.