2010-10-26 17 views
15

Eventuali duplicati:
how to find the location of the executable in CUn eseguibile può scoprire il proprio percorso? (Linux)

Vorrei un eseguibile per essere in grado di scoprire il proprio percorso; Ho la sensazione che la risposta sia "non puoi farlo", ma vorrei che fosse confermata!

Non penso di poter utilizzare getcwd(), perché potrei non eseguirlo dalla stessa directory. Non penso di poter usare argv[0], perché si basa sulla stringa utilizzata per eseguirla. Ci sono altre opzioni?

Razionale

Il vero problema è che mi piacerebbe mettere un eseguibile da qualche parte su un file system, e inserire un file predefinito di configurazione accanto ad esso. Voglio che l'eseguibile sia in grado di leggere il suo file di configurazione in fase di esecuzione, ma non voglio inserire questa posizione nel file eseguibile, né voglio che l'utente debba impostare le variabili di ambiente. Se c'è una soluzione migliore per questa situazione, io sono tutte le orecchie ...

+2

"Se c'è una soluzione migliore a questa situazione", Sì, fai come fa il resto del mondo, metti il ​​file di configurazione nella directory/etc. – Anders

+0

@Steve: Sì, la risposta a questa domanda è esattamente quello che sto cercando. Grazie! –

+0

è una risposta modello, lieto che abbia aiutato –

risposta

27

Il file/proc/self/exe è un simlink per l'eseguibile attualmente in esecuzione.

+7

Questo link simbolico deve essere letto con readlink. – Aif

1

Bene, devi usare getcwd() in congiunzione con argv[0]. Il primo ti dà la directory di lavoro, il secondo ti dà la posizione relativa del binario dalla directory di lavoro (o un percorso assoluto).

+0

e perché downvote anche questo? qualcuno è zoppo .. –

+2

Non ho fatto un downvote, ma non penso che funzioni. 'argv [0]' non è necessariamente relativo (considera l'esecuzione di un eseguibile da riga di comando come '/ blah/my_app'). –

+0

Programmi da eseguire non cercati in cwd, ma in $ PATH, fino a quando non si specifica il percorso all'eseguibile. – Vovanium

5

Utilizzare il proc filesystem

Il flusso sarebbe:

  • Get pid del eseguibile
  • un'occhiata a /proc/PID/exe per un collegamento simbolico
+0

perché il downvote? e perché solo minimizzare il mio quando CodeninjaTim fondamentalmente dice la stessa cosa? –

+5

Non c'è bisogno di ottenere il pid e manipolare dinamicamente le stringhe. La stringa hard-coded '"/proc/self/exe "' è più semplice e migliore. –

12

È possibile utilizzare getpid() per trovare la pid del processo corrente, quindi leggere /proc/<pid>/cmdline (per un lettore umano) o /proc/<pid>/exe che è un collegamento simbolico all'attuatore al programma. Quindi, usando readlink(), puoi trovare il percorso completo del programma.

Ecco un'implementazione in C:

#include <sys/types.h> 
#include <unistd.h> 
#include <sys/stat.h> 
#include <limits.h> 
#include <stdio.h> 

int main() 
{ 
    char path[PATH_MAX]; 
    char dest[PATH_MAX]; 
    memset(dest,0,sizeof(dest)); // readlink does not null terminate! 
    struct stat info; 
    pid_t pid = getpid(); 
    sprintf(path, "/proc/%d/exe", pid); 
    if (readlink(path, dest, PATH_MAX) == -1) 
    perror("readlink"); 
    else { 
    printf("%s\n", dest); 
    } 
    return 0; 
} 

Se volete provare, potete quindi compilare questo, fare un collegamento simbolico dal file eseguibile ad un altro percorso, e chiamare il link:

$ gcc -o mybin source.c 
$ ln -s ./mybin /tmp/otherplace 
$ /tmp/otherplace 
/home/fser/mybin 
+3

Come indicato nella risposta di @ Cercerilla, '/ proc/self/exe' funziona proprio come'/proc//exe', e non devi perderti di trovare il tuo pid. –

+2

è vero, sto usando 'self' di recente! – Aif

1

Ottieni il tuo nome da argv[0] quindi chiama il comando which. Questo obv funziona solo se il tuo eseguibile è in $PATH.

Problemi correlati