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

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

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

Ответ 1

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

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

Ответ 2

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

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

Ответ 3

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

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

Ответ 4

Я использую:

ps -ef | grep 786

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

Ответ 5

pwdx <process id>

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

Ответ 6

В 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 

Ответ 7

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

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

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

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

Ответ 8

спасибо:  Киви
с 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
}

Ответ 9

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

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

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

Ответ 10

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

Например:

[[email protected]:/home2/Avro/AvroGen]$ ps1 nifi

18404: /home2/Avro/NIFI

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

Ответ 11

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

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