2009-03-03 4 views

risposta

124

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

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

+1

'sudo' se l'output è vuoto, alcuni processi vengono creati da altri utenti di sistema. – Lun4i

4

In Linux ogni processo ha una propria cartella in /proc. Quindi è possibile utilizzare getpid() per ottenere il pid del processo in esecuzione e quindi aggiungerlo con il percorso /proc per 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 in ANSI C così:

#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; 
} 

Compilatelo con:

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

buono, ma ho bisogno dell'uso C ANSI. Serbatoi – lsalamon

+0

uscita Python su una versione recente di Ubuntu: >>> import os >>> os.path.join di stampa ('/ proc', str (os.getpid())) /proc/24346 –

2

Non c'è "garantiti per lavorare ovunque "metodo.

Il passaggio 1 è controllare argv [0], se il programma è stato avviato dal relativo percorso completo, questo (in genere) ha il percorso completo. Se è stato avviato da un percorso relativo, lo stesso vale (sebbene ciò richieda di ottenere la directory di lavoro corrente, usando getcwd().

Il passaggio 2, se nessuno dei precedenti contiene, è quello di ottenere il nome del programma, quindi ottenere il nome del programma da argv [0], quindi ottenere il PATH dell'utente dall'ambiente e passare attraverso quello per vedere se c'è un binario eseguibile adatto con lo stesso nome

Nota che argv [0] è impostato dal processo che exec il programma, quindi è affidabile al 100%.

26

EDITORI NOTAil codice sotto ha un bug. readlink non lo fa n ull terminare la stringa di output, quindi se funziona, è stato un incidente.

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

Se avete bisogno anche unix, allora avete 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 */ 
    if (readlink ("/proc/self/exe", path, dest_len) != -1) 
    { 
     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; 
} 
+0

Grazie per condividere Hiperion, ma avevo bisogno di specificare un PID e ottenere il suo percorso exe, è possibile con questo codice? – Noitidart

+1

@Noitidart - sostituisce '"/proc/self/exe "' con 'sprintf (foo,"/proc /% d/exe ", pid)' –

+1

Si noti che readlink non annulla il risultato, quindi questo codice ha comportamento indefinito. –

-1

Trova il percorso di 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

Spiega il tuo codice. Se lo copi e lo incolli da un'altra posizione, ti preghiamo di collegarti alla fonte. – Tim

+0

Ciò che questo codice non è efficiente sta ottenendo il nome del processo (in sostanza, la riga "PID" è una sostituzione di 'pgrep'); nella riga successiva ottiene il percorso del file binario che viene eseguito ('/ proc/$ PID/exe' è un collegamento simbolico al file eseguibile); e infine fa eco a quel link simbolico. – Enrico

1

È possibile anche ottenere il percorso su GNU/Linux con (non a fondo 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 la directory dell'eseguibile per forse la modifica della directory di lavoro ai processi directory di s (per i media/dati/etc), è necessario mollare tutto dopo l'ultimo /:

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

È possibile trovare l'exe facilmente da questi modi, basta provarlo voi stessi.

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

io uso:

ps -ef | grep 786 

Sostituire 786 con il PID o il nome del processo.

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 
} 
+0

PERFETTO che qualcuno ne abbia fatto uno script – Kiwy

0

pwdx <process id>

Questo comando verrà recuperato il percorso processo da cui è in esecuzione.

+0

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