Come posso ottenere il percorso di un processo in Unix / Linux


138

In ambiente Windows è presente un'API per ottenere il percorso che esegue un processo. C'è qualcosa di simile in Unix / Linux?

O c'è un altro modo per farlo in questi ambienti?

Risposte:


183

Su Linux, il collegamento simbolico /proc/<pid>/exeha il percorso dell'eseguibile. Utilizzare il comando readlink -f /proc/<pid>/exeper ottenere il valore.

Su AIX, questo file non esiste. Puoi confrontare cksum <actual path to binary>e cksum /proc/<pid>/object/a.out.


2
sudose l'output è vuoto, alcuni processi vengono creati da altri utenti del sistema.
Lun4i,

63

Puoi trovare facilmente l'exe in questi modi, provalo tu stesso.

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

1
Questo e spettacolare. Sapevo di averlo eseguito da una posizione che aveva il collegamento simbolico all'eseguibile originale (una delle tante versioni). pwdx <PID>mi ha dato la posizione del collegamento simbolico in modo da poter trovare i registri e interrompere il processo in modo corretto.
NurShomik,

1
lldi solito è un alias: alias ll='ls -alF'.
Pablo A

1
Gli ultimi due (pwdx e lsof) potrebbero non dare il risultato corretto. La domanda riguardava il percorso completo dell'eseguibile. pwdx e lsof ti daranno la CWD del processo piuttosto che il percorso del processo. Penso che la risposta di jpalecek sia più accurata in quanto il richiedente originale ha chiesto il percorso dell'eseguibile piuttosto che il soft link che descrive l'eseguibile.
Shimon,

28

Un po 'in ritardo, ma tutte le risposte erano specifiche per Linux.

Se hai bisogno anche di unix, allora hai bisogno di questo:

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: corretto il bug segnalato da Mark lakata.


Grazie per aver condiviso Hiperion, ma dovevo specificare un PID e ottenere il suo percorso exe, è possibile con questo codice?
Noitidart,

1
@Noitidart - sostituisci "/proc/self/exe"consprintf(foo,"/proc/%d/exe",pid)
Mark Lakata,

2
Si noti che readlink non annulla il risultato, quindi questo codice ha un comportamento indefinito.
Mark Lakata,

Grazie @MarkLakata! :)
Noitidart

Grazie per aver notato @MarkLakata
Hiperion il

14

Io uso:

ps -ef | grep 786

Sostituisci 786 con il tuo PID o nome del processo.


11

pwdx <process id>

Questo comando recupererà il percorso del processo da dove viene eseguito.


La domanda riguarda l'API per ottenere informazioni, ma grazie comunque.
lsalamon il

4

In Linux ogni processo ha la sua cartella in /proc. Quindi è possibile utilizzare getpid()per ottenere il pid del processo in esecuzione e quindi unirlo al percorso /procper ottenere la cartella che si spera sia necessaria.

Ecco un breve esempio in Python:

import os
print os.path.join('/proc', str(os.getpid()))

Ecco l'esempio anche in 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;
}

Compilalo con:

gcc -Wall -Werror -g -ansi -pedantic process_path.c -oprocess_path 

Uscita Python su una versione recente di Ubuntu: >>> import os >>> print os.path.join ('/ proc', str (os.getpid ())) / proc / 24346
Luke Stanley,

3

Non esiste un metodo "garantito per funzionare ovunque".

Il passo 1 è controllare argv [0], se il programma è stato avviato con il suo percorso completo, questo (di solito) avrebbe il percorso completo. Se è stato avviato da un percorso relativo, lo stesso vale (sebbene ciò richieda ottenere la directory di lavoro corrente, usando getcwd ().

Il passaggio 2, se nessuna delle precedenti è valido, è ottenere il nome del programma, quindi ottenere il nome del programma da argv [0], quindi ottenere il PERCORSO dell'utente dall'ambiente e passare attraverso quello per vedere se esiste un binario eseguibile con lo stesso nome.

Si noti che argv [0] è impostato dal processo che esegue il programma, quindi non è affidabile al 100%.


2

grazie: Kiwy
con 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
}

Bello che qualcuno ne ha fatto una sceneggiatura
Kiwy,

1

Puoi anche ottenere il percorso su GNU / Linux con (non accuratamente testato):

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

Se si desidera che la directory dell'eseguibile possa cambiare la directory di lavoro nella directory del processo (per media / dati / ecc.), È necessario eliminare tutto dopo l'ultimo /:

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

1

Il comando seguente cerca il nome del processo nell'elenco dei processi in esecuzione e reindirizza il comando pid su pwdx per trovare la posizione del processo.

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

Sostituisci "abc" con il tuo modello specifico.

In alternativa, se è possibile configurarlo come funzione in .bashrc, può essere utile da utilizzare se è necessario utilizzarlo frequentemente.

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

Ad esempio:

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

18404: /home2/Avro/NIFI

Spero che questo aiuti qualcuno a volte .....


-1

Trova il percorso per un nome di processo

#!/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
Per favore, spiega il tuo codice. Se lo copi e lo incolli da altrove, ti preghiamo di collegarti alla fonte.
Tim

Quello che sta facendo questo codice, non così efficiente, è ottenere il nome del processo (essenzialmente, la riga "PID" è un rimpiazzo pgrep); nella riga successiva ottiene il percorso del binario in esecuzione ( /proc/$PID/exeè un collegamento simbolico al file eseguibile); e infine fa eco a quel link simbolico.
Enrico,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.