warum ignoriert strace meinen alias für rm?

8

Ich habe ein aliasSet für meinen rmBefehl. Wenn ich einen aliasBefehl ausführe , erhalte ich diesen als Ausgabe.

alias rm='rm -i'

Wenn ich jetzt den rmBefehl ausführe , funktioniert er wie erwartet.

rm ramesh
rm: remove regular empty file `ramesh'? y

Jetzt lernte ich die Systemaufrufe, die aufgerufen werden, wenn ich einen Befehl ausführe. Dafür habe ich stracevon hier aus den Befehl kennengelernt, der mir die Dateien auflistet, die aufgerufen werden, wenn ich einen Befehl ausführe. Der Befehl ist wie folgt.

strace -ff -e trace=file rm ramesh 2>&1 

Der Befehl funktioniert einwandfrei, außer dass er meine Aliase ignoriert, die ich für meinen rmBefehl eingerichtet habe. Die Datei wird gelöscht, ohne dass der Benutzer dazu aufgefordert wird.

Von daher ist straceAliase wie diese ignorieren? Wenn ja, warum ist es so?

BEARBEITEN:

Ich bin type -a rmmir nicht sicher, ob dies etwas zu tun hat, aber ich gebe die Ausgabe als,

rm is aliased to `rm -i'
rm is /bin/rm

Berücksichtigt man /bin/rmin diesem Fall, warum der Benutzer nicht vor dem Löschen aufgefordert wird?

Ramesh
quelle
3
straceignoriert Aliase nicht, da dies bedeuten würde, dass überhaupt etwas zu ignorieren wäre. Ein Alias ​​ist ein Merkmal der Shell. straceist ein anderes Programm, und innerhalb stracedes Konzepts der Aliase existiert nicht, daher gibt es nichts zu ignorieren. Die vom Kernel bereitgestellte API zum Ausführen von Programmen enthält ebenfalls kein Aliase-Konzept. Daher kann die Shell auf keinen Fall einen Hinweis auf Aliase geben, selbst wenn dies gewünscht wird.
Kasperd
1
Wenn Sie straceeinen Alias möchten , müssen Sie stracedie Shell verwenden, die den Alias ​​implementiert. Es gibt einige Ansätze, die Sie dazu strace -p $$ &strace bashstrace sh -c 'rm ramesh'
wählen

Antworten:

20

straceläuft nicht rm -iaus dem gleichen Grund wie:

echo rm

wird nicht ausgegeben rm -i .

Aliase sind ein Merkmal einiger Shells, mit denen einige Zeichenfolgen automatisch durch andere ersetzt werden können, wenn sie sich in der Befehlsposition befinden.

Im:

alias foo='whatever'
foo xxx

Die Muscheln erweitern das auf:

whatever xxx

und das durchläuft eine weitere Interpretationsrunde, die in diesem Fall zur Ausführung des whatever Befehls führt.

Aliase werden nur erweitert, wenn sie an der Befehlsposition gefunden werden (als erstes Wort einer Befehlszeile).

zshunterstützt globale Aliase.

Du könntest es tun:

alias -g rm='rm -i'

Aber du würdest nicht wollen, denn das würde bedeuten:

echo rm

würde rm -izum Beispiel ausgeben .

Stéphane Chazelas
quelle
8

straceVerwendet die PATHUmgebungsvariable, um das zu verfolgende Programm zu lokalisieren, anstatt es über die Shell auszuführen (was die Ausgabe überladen würde). Ein Shell-Alias ​​ist kein Programm, sondern eine Funktion der Shell und wird daher straceignoriert.

Laufen strace strace rmist ziemlich aufschlussreich und interessant rekursiv.

Kennzeichen
quelle
5

Ein Alias ​​ist eine Funktion Ihrer Shell. Strace führt den Befehl jedoch direkt aus ( execvewahrscheinlich mit), wobei die Shell nicht beteiligt ist. (Wenn strace den angegebenen Befehl über die Shell ausführt, enthält die Ausgabe von strace alle Shell-Ausführungs-Systemaufrufe und nicht nur die aus dem interessierenden Prozess.)

Darüber hinaus versucht strace rm rameshdie interaktive Shell beim Ausführen nicht, Ihren Alias ​​in den Argumenten zu ersetzen, da dies für alle schrecklich verwirrend wäre. Die Shell erweitert nur Aliase, die an der ersten Position in einer Befehlszeile angezeigt werden.

Greg Hewgill
quelle
2

strace verwendet execve c functionwie find command, jedoch können find uses exec functionSie nicht verwenden aliases, built-in shell commandoder so weiter.

Du musst:

strace /bin/rm -i ramesh
Persischer Golf
quelle
2

Um auf der Antwort von Stéphane Chazelas aufzubauen, wenn Sie definieren

alias strace="strace "

(mit einem Leerzeichen am Ende) dann der Befehl

strace rm ramesh

wird verarbeitet als

strace rm -i ramesh

Aber selbst dies funktioniert nur für das erste Wort nach dem strace, sodass es nicht direkt auf Ihr Beispiel zutrifft (wo Sie intervenierende Optionen haben).  Aber wenn Sie definieren

alias my_strace="strace -ff -e trace=file "

dann

my_strace rm ramesh

wird verarbeitet als

strace -ff -e trace=file rm -i ramesh
G-Man sagt "Reinstate Monica"
quelle
2

Keine Aliase hier

Nehmen wir an, wir haben die Alias-Definition alias rm='rm -i'in unserer ~/.bashrc. Der Alias ​​fügt die Option zum Auffordern vor dem Entfernen jeder Datei hinzu:

$ touch ./file
$ rm ./file
/bin/rm: remove regular empty file ‘./file’? 

Es ist nicht die Schuld, stracedass der Alias ​​nicht verwendet wurde:
Es hat einfach nichts mit Aliasen zu tun.

Im Befehl

$ strace -f -e file -o rm.strace rm ./file

Die Wörter rmund ./filesind vorerst nur Argumente für strace - die Shell kann den Alias ​​nicht erweitern rm, da sie nicht wissen kann, dass strace diese Argumente später als Befehl verwendet.

Im Allgemeinen können Befehls-Aliase nur dort verwendet werden, wo Befehle verwendet werden können.

Aliase sind eine Funktion der Shell und verwenden straceüberhaupt keine Shell, wenn der Befehl über die Befehlszeile aufgerufen wird. Es wird exec()stattdessen mit den Befehlen und Argumenten aus der eigenen Befehlszeile verwendet.

Innerhalb von strace, wird der Befehl mit etwas ähnlichem genannt werden exec("rm", "file"), und exec()findet /bin/rmin PATH - ohne eine Shell zu verwenden.

Explizite Shell

Warum nicht eine Shell in den straceBefehl aufnehmen?

$ touch ./file
$ strace -f -e file -o rm.strace bash -c 'rm ./file'
$ ls ./file
ls: cannot access ./file: No such file or directory

Hmm ... das hat nicht funktioniert. rmhabe gerade die Datei ohne -iAufforderung gelöscht .

Interaktive Aliase

Aliase werden normalerweise nur in interaktiven Shells aktiviert, den tatsächlichen Befehlszeilen in einem Terminal.
Bei unserem Beispielalias ist leicht zu erkennen, warum dies sinnvoll ist: Wenn der rm -iAlias ​​in Shell-Skripten erweitert würde, würden sie beim ersten Mal hängen bleiben, ohne dass jemand rmzum Drücken da wäre y.

Aliase werden von der Shell-Option gesteuert expand_aliases. Wir könnten die Option mit einstellen bash +O expand_aliases -c .... Das reicht aber nicht, denn die nicht interaktive Shell liest auch nicht ~/.bashrc. Das heißt, unser Alias ​​wird nicht nur durch die Option ausgeschaltet, sondern auch nicht einmal definiert.

Vorgeben, interaktiv zu sein

Die einfache Möglichkeit, beide Teile zu handhaben, besteht darin, die Befehlszeilenoption -izu verwenden, damit die Shell so tut, als wäre sie interaktiv:

$ touch ./file
$ strace -f -e file -o rm.strace bash -i -c 'rm ./file'
/bin/rm: remove regular empty file ‘./file’?

Schließlich wurde der -iAlias ​​verwendet!

Beachten Sie, dass Sie normalerweise keine Shells verwenden würden, die mit der -iOption zum Erstellen von Skripten ausgeführt werden, selbst wenn Sie beispielsweise Ihre Aliase verfügbar haben möchten.

Volker Siegel
quelle