Typische Unix / Linux-Programme akzeptieren die Kommandozeilen-Eingaben als Argument count ( int argc
) und als Argument vector ( char *argv[]
). Das erste Element von argv
ist der Programmname, gefolgt von den eigentlichen Argumenten.
Warum wird der Programmname als Argument an die ausführbare Datei übergeben? Gibt es Beispiele für Programme, die ihren eigenen Namen verwenden (möglicherweise in einer bestimmten exec
Situation)?
command-line
c
arguments
Shrikant Giridhar
quelle
quelle
sh
ist symlink zudash
. Sie verhalten sich anders, wenn sie aufgerufen wird, wiesh
oder alsdash
busybox
(üblich bei Rettungsdiscs und dergleichen) verwenden, dann ist so ziemlich alles (cp, mv, rm, ls, ...) ein symbolischer Link zu busybox.gcc
,bash
,gunzip
, die meisten der Rest des OS ...), da Linux nur der Kernel ist.Antworten:
Beachten Sie zunächst, dass dies
argv[0]
nicht unbedingt der Programmname ist. Dies ist, was der Aufrufer inargv[0]
denexecve
Systemaufruf einfügt (siehe z. B. diese Frage zum Stapelüberlauf ). (Alle anderen Varianten vonexec
sind keine Systemaufrufe, sondern Schnittstellen zuexecve
.)Angenommen, zum Beispiel
execl
:/var/tmp/mybackdoor
wird ausgeführt,argv[0]
ist aber auf gesetzttop
, und dies wird angezeigtps
oder (der echte)top
. Weitere Informationen finden Sie in dieser Antwort auf U & L SE.Das alles beiseite legen: Vor dem Aufkommen von ausgefallenen Dateisystemen wie
/proc
,argv[0]
war der einzige Weg für einen Prozess, etwas über seinen eigenen Namen zu lernen. Wofür wäre das gut?quelle
bunzip2
,bzcat
undbzip2
, für die ersten zwei symbolische Links zu dem dritten sind.zcat
ist kein Symlink. Sie scheinen die Nachteile dieser Technik zu vermeiden, indem sie stattdessen ein Shell-Skript verwenden. Sie können jedoch keine vollständige--help
Ausgabe drucken, da jemand, der gzip-Optionen hinzugefügt hat, vergessen hat, auch zcat zu verwalten.gunzip
ist eine historische Ausnahme.argv[0]
Nutzungs- / Hilfeausgabe hinzu, anstatt ihren Namen fest zu codieren. Einige sind vollständig, andere nur der Basisname.Reichlich:
argv[0]
istsh
. Es wird als Anmeldeshell ausgeführt, wennargv[0]
mit begonnen wird-
.vi
,view
,evim
,eview
,ex
,vimdiff
, usw.shutdown
,reboot
usw. sind Symlinkssystemctl
.quelle
sendmail
undmail
. Jeder einzelne Unix-MTA wird mit einem Symlink für diese beiden Befehle ausgeliefert und soll das Verhalten des Originals nachahmen, wenn es als solches aufgerufen wird. Dies bedeutet, dass jedes Unix-Programm, das E-Mails senden muss, genau weiß, wie es dies tun kann.test
und[
: Wenn Sie den ersteren aufrufen, wird ein Fehler behandelt, wenn das letzte Argument lautet]
. (Auf Debian Stable sind diese Befehle zwei verschiedene Programme, aber frühere Versionen und MacOs verwenden immer noch dasselbe Programm). Undtex
,latex
und so weiter: die binären gleich ist, aber auf der Suche , wie es genannt wurde, wählen sie die richtige Konfiguration Datei.init
ist ähnlich.[
betrachtet es als Fehler, wenn das letzte Argument nicht ist]
.Historisch gesehen
argv
ist es nur ein Array von Zeigern auf die "Wörter" der Kommandozeile, daher ist es sinnvoll, mit dem ersten "Wort" zu beginnen, das zufällig der Name des Programms ist.Und es gibt eine ganze Reihe von Programmen, die sich je nach dem Namen, unter dem sie aufgerufen werden, unterschiedlich verhalten. Sie können also einfach verschiedene Links zu ihnen erstellen und verschiedene "Befehle" abrufen. Das extremste Beispiel, an das ich denken kann, ist die Busybox , die sich je nach Aufruf wie ein Dutzend verschiedener "Befehle" verhält .
Bearbeiten : Referenzen für Unix 1. Ausgabe, wie angefordert
Man kann beispielsweise von der siehe Hauptfunktion dass und wurden bereits verwendet. Die Shell - Kopien Argumente an die im Inneren der Teil der Schlaufe, während die sich als die Argumente in der gleichen Art und Weise der Behandlung von Befehl. (Später führt es natürlich nur das erste Argument aus, das der Name des Befehls ist.) Anscheinend gab es damals keine Verwandten.
cc
argc
argv
parbuf
newarg
execv
quelle
exec
den Namen des auszuführenden Befehls und ein nullterminiertes Array von Zeichenzeigern (am besten zu sehen unter minnie.tuhs.org/cgi-bin/utree.pl?file=V1/u0.s , woexec
nimmt Verweise auf Label 2 und Label 1 und auf Label2:
erscheinenetc/init\0
, und auf Label1:
erscheint ein Verweis auf Label 2 und eine abschließende Null, was im Grunde das ist, wasexecve
heute minus bedeutetenvp
.execv
undexecl
existierten "für immer" (dh seit Anfang bis Mitte der 1970er Jahre) -execv
war ein Systemaufruf undexecl
war eine Bibliotheksfunktion, die ihn aufrief.execve
gab es damals nicht, weil es die umgebung damals nicht gab. Die anderen Familienmitglieder wurden später hinzugefügt.execv
die v1-Quelle verweisen, auf die ich verlinkt habe? Nur neugierig.Anwendungsfälle:
Sie können den Programmnamen verwenden , um das Programmverhalten zu ändern .
Beispielsweise könnten Sie einige Symlinks zur eigentlichen Binärdatei erstellen.
Ein bekanntes Beispiel für diese Technik ist das Projekt busybox, bei dem nur eine einzige Binärdatei und viele Symlinks darauf installiert werden. (ls, cp, mv, etc). Sie tun dies , um Speicherplatz zu sparen, da ihre Ziele kleine eingebettete Geräte sind.
Dies wird auch in
setarch
util-linux verwendet:Hier verwenden sie diese Technik im Wesentlichen , um viele doppelte Quelldateien zu vermeiden oder um die Quellen besser lesbar zu halten.
Ein weiterer Anwendungsfall wäre ein Programm, das zur Laufzeit einige Module oder Daten laden muss. Mit dem Programmpfad können Sie Module von einem Pfad relativ zum Programmspeicherort laden .
Darüber hinaus geben viele Programme Fehlermeldungen aus, einschließlich des Programmnamens .
Warum :
man 3p execve
):Beachten Sie, dass der C-Standard "Programmname" und nicht "Dateiname" sagt.
quelle
Zusätzlich zu Programmen, die ihr Verhalten je nach Aufruf ändern, kann ich
argv[0]
die Verwendung eines Programms folgendermaßen drucken:Dies bewirkt, dass die Verwendungsnachricht immer den Namen verwendet, unter dem sie aufgerufen wurde. Wenn das Programm umbenannt wird, ändert sich seine Verwendungsmeldung mit. Es enthält sogar den Pfadnamen, mit dem es aufgerufen wurde:
Es ist eine nette Geste, besonders für kleine Spezialwerkzeuge / Skripte, die überall zu finden sind.
Dies scheint auch in GNU-Tools üblich zu sein, siehe
ls
zum Beispiel:quelle
Man führt das Programm die Eingabe:
program_name0 arg1 arg2 arg3 ...
.Die Shell sollte das Token also bereits teilen, und das erste Token ist bereits der Programmname. Übrigens gibt es auf der Programmseite und auf der Shell die gleichen Indizes.
Ich denke, dies war nur ein Convenience-Trick (von Anfang an), und wie Sie in anderen Antworten sehen, war er auch sehr praktisch, sodass diese Tradition fortgesetzt und als API festgelegt wurde.
quelle
Grundsätzlich enthält argv den Programmnamen, so dass Sie Fehlermeldungen wie
prgm: file: No such file or directory
die folgenden schreiben können :quelle
Ein weiteres Anwendungsbeispiel hierfür ist dieses Programm, das sich durch ... sich selbst ersetzt, bis Sie etwas eingeben, das nicht mehr vorhanden ist
y
.Offensichtlich ein ausgeklügeltes, wenn auch interessantes Beispiel, aber ich denke, dies könnte realen Nutzen haben - zum Beispiel eine sich selbst aktualisierende Binärdatei, die ihren eigenen Speicherplatz mit einer neuen Version von sich selbst überschreibt, die sie heruntergeladen oder geändert hat.
Beispiel:
Quelle und ein paar mehr Infos .
quelle
Der Pfad zum Programm lautet
argv[0]
, damit das Programm Konfigurationsdateien usw. aus seinem Installationsverzeichnis abrufen kann.Ohne wäre das unmöglich
argv[0]
.quelle
(char *path_to_program, char **argv, int argc)
zum Beispiel~/.<program>
,/etc/<program
,$XDG_CONFIG_HOME
) und entweder einen Parameter nehmen , sie zu ändern oder eine Compiler-Option, die die binären in einem konstanten backt.ccache verhält sich so, um verschiedene Aufrufe von Compiler-Binärdateien nachzuahmen. ccache ist ein Kompilierungscache - der springende Punkt ist, niemals denselben Quellcode zweimal zu kompilieren, sondern den Objektcode, wenn möglich, aus dem Cache zurückzugeben.
Auf der Manpage " ccache " gibt es zwei Möglichkeiten, ccache zu verwenden. Sie können Ihren Kompilierungsbefehlen entweder ccache voranstellen oder ccache als Compiler maskieren lassen, indem Sie einen symbolischen Link (als Compiler bezeichnet) zu ccache erstellen. Die erste Methode Dies ist am praktischsten, wenn Sie Ccache nur ausprobieren oder für bestimmte Projekte verwenden möchten. Die zweite Methode ist am nützlichsten, wenn Sie Ccache für alle Ihre Kompilierungen verwenden möchten. "
Bei der symlinks-Methode werden die folgenden Befehle ausgeführt:
... die Folge ist, dass ccache alle Befehle abfängt, die ansonsten an die Compiler gegangen wären. Auf diese Weise kann ccache eine zwischengespeicherte Datei zurückgeben oder den Befehl an den eigentlichen Compiler weiterleiten.
quelle