Kann eine ausführbare Datei ihren eigenen Pfad entdecken? (Linux) [duplicate]

Lesezeit: 6 Minuten

Benutzer-Avatar
Oliver Charlesworth

Mögliches Duplikat:

So finden Sie den Speicherort der ausführbaren Datei in C

Ich möchte, dass eine ausführbare Datei ihren eigenen Pfad entdecken kann; Ich habe das Gefühl, dass die Antwort lautet: “Das können Sie nicht”, aber ich möchte, dass dies bestätigt wird!

Ich glaube nicht, dass ich es verwenden kann getcwd(), da ich es möglicherweise nicht aus demselben Verzeichnis ausführe. Ich glaube nicht, dass ich es verwenden kann argv[0], da dies auf der Zeichenfolge basiert, die zur Ausführung verwendet wird. Gibt es noch andere Möglichkeiten?

Begründung

Das eigentliche Problem ist, dass ich eine ausführbare Datei irgendwo in einem Dateisystem platzieren und daneben eine Standardkonfigurationsdatei platzieren möchte. Ich möchte, dass die ausführbare Datei ihre Konfigurationsdatei zur Laufzeit lesen kann, aber ich möchte diesen Speicherort nicht fest in die ausführbare Datei codieren, und ich möchte auch nicht, dass der Benutzer Umgebungsvariablen festlegen muss. Wenn es eine bessere Lösung für diese Situation gibt, bin ich ganz Ohr…

  • “Wenn es eine bessere Lösung für diese Situation gibt”, ja, tun Sie es wie der Rest der Welt, legen Sie die Konfigurationsdatei in das /etc-Verzeichnis.

    – Anders

    26. Oktober 2010 um 15:49 Uhr

  • @Steve: Ja, die Antwort auf diese Frage ist genau das, wonach ich suche. Vielen Dank!

    – Oliver Charlesworth

    26. Oktober 2010 um 15:56 Uhr

  • Es ist eine Musterantwort, froh, dass das geholfen hat

    – Steve Townsend

    26. Oktober 2010 um 15:58 Uhr

  • @Anders: Der Grund, warum ich das nicht tun kann, ist, dass dies auf einer NFS-Freigabe sein wird, die jeder verwenden kann. Ich kann es nicht in jedermanns Lokal setzen /etc Verzeichnis!

    – Oliver Charlesworth

    26. Oktober 2010 um 15:58 Uhr

Die Datei /proc/self/exe ist ein Simlink auf die aktuell laufende ausführbare Datei.

  • Dieser Symlink sollte mit readlink gelesen werden.

    – Aif

    26. Oktober 2010 um 16:03 Uhr

  • Hier gibt es eine Readlink-Implementierung: stackoverflow.com/questions/5525668/…

    – Aaron Schwan

    5. April 2019 um 16:32 Uhr

Benutzer-Avatar
Aif

Bearbeiten: Es wurde darauf hingewiesen, dass mit /proc/self/exe ist direkter. Das ist völlig richtig, aber ich habe keinen Nutzen darin gesehen, den Code zu bearbeiten. Da ich immer noch Kommentare dazu bekomme, habe ich es bearbeitet.

#include <unistd.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>

int main()
{
  char dest[PATH_MAX];
  memset(dest,0,sizeof(dest)); // readlink does not null terminate!
  if (readlink("/proc/self/exe", dest, PATH_MAX) == -1) {
    perror("readlink");
  } else {
    printf("%s\n", dest);
  }
  return 0;
}

Erste Antwort:
Sie können getpid() verwenden, um die PID des aktuellen Prozesses zu finden, und dann lesen /proc/<pid>/cmdline (für einen menschlichen Leser) oder /proc/<pid>/exe das ist ein symbolischer Link zum eigentlichen Programm. Dann können Sie mit readlink() den vollständigen Pfad des Programms finden.

Hier ist eine Implementierung in C:

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

int main()
{
  char path[PATH_MAX];
  char dest[PATH_MAX];
  memset(dest,0,sizeof(dest)); // readlink does not null terminate!
  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;
}

Wenn Sie es versuchen möchten, können Sie dies kompilieren, einen Symlink von der ausführbaren Datei zu einem anderen Pfad erstellen und den Link aufrufen:

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

  • Wie in der Antwort von @Cercerilla erwähnt, /proc/self/exe funktioniert genauso wie /proc/<PID>/exeund Sie müssen sich nicht damit herumschlagen, Ihre eigene PID herauszufinden.

    – Tim Ruddick

    19. September 2014 um 17:30 Uhr

  • das ist richtig, ich habe verwendet self in letzter Zeit!

    – Aif

    21. September 2014 um 0:50 Uhr

  • Ihre Strategie von /proc/.../exe ist der richtige. Verwenden snprintf (beachten Sie das n) Anstatt von sprintf. Verwenden %ld Anstatt von %d und wirf die pid zu long. Verwenden /proc/self/exe vermeidet diese beiden Bedenken. Speichern Sie die readlink() resultieren ssize_t n; und überprüfe das (size_t)n < sizeof(dest).

    – Lassi

    19. März 2020 um 10:02 Uhr


  • @Lassi Danke für deinen Kommentar! Die Annahme bei sprintf (im Gegensatz zu snprintf) war, dass wir einen vorhandenen Pfad in einen statisch zugewiesenen kopieren PATH_MAX. Implizit davon ausgegangen, dass der vorhandene Pfad nicht größer sein könnte. Sehen Sie ein praktisches Szenario, in dem das nicht der Fall sein könnte?

    – Aif

    19. März 2020 um 11:38 Uhr

  • Nein – Sie haben Recht, dass es in diesem Fall kein praktisches Szenario gibt. Der Grund ist einfach sprintf und strcpy werden so oft unsicher verwendet, dass erfahrene C-Programmierer sie für keinen Zweck mehr empfehlen und Compiler/Linter möglicherweise davor warnen. Verwenden snprintf stattdessen ist ein “Ich weiß, was ich tue”-Signal, das zumindest sicherstellt, dass Fehler im Code nicht zu Pufferüberläufen führen. Es ist möglich zu überprüfen, ob einzelne Verwendungen von sprintf und strcpy sind richtig, aber es ist fehleranfällig und in einer großen Codebasis viel Aufwand.

    – Lassi

    19. März 2020 um 12:12 Uhr

Verwenden Sie die proc Dateisystem

Ihr Ablauf wäre:

  • Holen Sie sich die PID der ausführbaren Datei
  • ansehen /proc/PID/exe für einen Symlink

  • warum die abwertung? und warum nur meine herabstimmen, wenn CodeninjaTim im Grunde dasselbe sagt?

    – N.G.

    26. Oktober 2010 um 15:55 Uhr

  • Es besteht keine Notwendigkeit, die PID abzurufen und Zeichenfolgen dynamisch zu manipulieren. Die hartcodierte Zeichenfolge "/proc/self/exe" ist einfacher und besser.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    26. Mai 2011 um 19:08 Uhr

  • Dies ist eine korrekte Lösung für Linux und verdient keine Ablehnung. /proc/self/exe ist eine einfachere Möglichkeit, dasselbe zu tun, aber das manuelle Einfügen der PID funktioniert immer noch gut.

    – Lassi

    19. März 2020 um 9:49 Uhr

Nun, Sie müssen verwenden getcwd() in Verbindung mit argv[0]. Der erste gibt Ihnen das Arbeitsverzeichnis, der zweite gibt Ihnen den relativen Speicherort der Binärdatei aus dem Arbeitsverzeichnis (oder einen absoluten Pfad).

Holen Sie sich Ihren Namen von argv[0] dann rufen Sie die an which Befehl. Dies funktioniert natürlich nur, wenn Ihre ausführbare Datei enthalten ist $PATH.

  • Leider argv[0] basierte Lösungen funktionieren nur zufällig. Es ist auch ratsam, das Aufrufen eines externen Befehls wie z which für einfache Aufgaben, da dies viele weitere Faktoren hinzufügt, die kaputt gehen können. Für Linux gibt es zwar keine tragbare und zuverlässige Lösung readlink("/proc/self/exe") ist einfach und richtig.

    – Lassi

    19. März 2020 um 9:54 Uhr

  • Leider argv[0] basierte Lösungen funktionieren nur zufällig. Es ist auch ratsam, das Aufrufen eines externen Befehls wie z which für einfache Aufgaben, da dies viele weitere Faktoren hinzufügt, die kaputt gehen können. Für Linux gibt es zwar keine tragbare und zuverlässige Lösung readlink("/proc/self/exe") ist einfach und richtig.

    – Lassi

    19. März 2020 um 9:54 Uhr

1256840cookie-checkKann eine ausführbare Datei ihren eigenen Pfad entdecken? (Linux) [duplicate]

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy