pourquoi strace ignore mon alias pour rm?

8

J'ai un aliasensemble pour ma rmcommande. Si j'exécute la aliascommande, c'est ce que j'obtiens en sortie.

alias rm='rm -i'

Maintenant, lorsque j'exécute la rmcommande, cela fonctionne bien comme prévu.

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

Maintenant, j'apprenais sur les appels système qui sont appelés lorsque j'exécute une commande. Pour cela, j'ai pris connaissance de la stracecommande d' ici qui me répertorie les fichiers qui sont appelés lorsque j'exécute une commande. La commande est comme ci-dessous.

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

La commande fonctionne parfaitement bien, sauf qu'elle ignore mes alias que j'ai en place pour ma rmcommande. Il supprime le fichier sans inviter l'utilisateur.

Alors, straceignore-t-il des alias comme celui-ci? Si oui, pourquoi en est-il ainsi?

ÉDITER:

Pas sûr, si cela a quelque chose à faire mais type -a rmme donne la sortie comme,

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

Envisage-t-il donc /bin/rmdans ce cas ce qui explique pourquoi l'utilisateur n'est pas invité avant la suppression?

Ramesh
la source
3
stracen'ignore pas les alias, car cela impliquerait qu'il y avait quelque chose à ignorer en premier lieu. Un alias est une caractéristique du shell. straceest un programme différent, et à stracel' intérieur du concept d'alias n'existe pas, donc il n'y a rien à ignorer. L'API fournie par le noyau pour l'exécution des programmes n'a pas non plus de concept d'alias, donc il n'y a aucun moyen que le shell puisse dire strace au sujet des alias, même s'il le voulait.
kasperd
1
Si vous voulez straceun alias, vous devez utiliser stracele shell, qui implémente l'alias. Il y a quelques approches que vous pouvez adopter pour faire cela: strace -p $$ &ou strace bashou strace sh -c 'rm ramesh'(la dernière ignorera également l'alias, mais pour une raison entièrement différente.)
kasperd

Réponses:

20

stracene fonctionne pas rm -ipour la même raison que:

echo rm

ne sort pas rm -i.

Les alias sont une fonctionnalité de quelques shells pour permettre à certaines chaînes d'être automatiquement remplacées par une autre lorsqu'elles sont trouvées en position de commande.

Dans:

alias foo='whatever'
foo xxx

Les obus élargissent cela pour:

whatever xxx

et qui subit une autre série d'interprétations, conduisant dans ce cas à l'exécution de la whatevercommande.

les alias ne sont développés que lorsqu'ils sont trouvés en position de commande (comme premier mot d'une ligne de commande).

zshprend en charge les alias mondiaux .

Vous pourriez faire:

alias -g rm='rm -i'

Mais vous ne voudriez pas, car cela signifierait que:

echo rm

produirait rm -ipar exemple.

Stéphane Chazelas
la source
8

straceutilise la PATHvariable d'environnement pour localiser le programme à tracer, plutôt que de l'exécuter via le shell (ce qui encombrerait la sortie). Un alias de shell n'est pas un programme, c'est une fonctionnalité du shell et l' straceignore donc.

Courir strace strace rmest plutôt instructif, tout en étant récursif de façon intéressante.

marque
la source
5

Un alias est une fonctionnalité de votre shell. Cependant, strace exécute la commande directement (en utilisant execve, probablement), ce qui n'implique pas le shell. (Si strace exécutait la commande donnée via le shell, la sortie de strace contiendrait tous les appels système d'exécution du shell plutôt que seulement ceux du processus d'intérêt.)

De plus, lorsque vous exécutez strace rm ramesh, le shell interactif n'essaie pas de remplacer votre alias dans les arguments à strace, car cela serait terriblement déroutant pour tout le monde. Le shell ne développe que les alias qui apparaissent en première position sur une ligne de commande.

Greg Hewgill
la source
2

strace utilise execve c functioncomme find command, Cependant, find uses exec functionvous ne pouvez pas utiliser aliases, built-in shell commandetc.

Tu dois faire:

strace /bin/rm -i ramesh
Golfe Persique
la source
2

Pour s'appuyer sur la réponse de Stéphane Chazelas, si vous définissez

alias strace="strace "

(avec un espace à la fin) puis la commande

strace rm ramesh

sera traité comme

strace rm -i ramesh

Mais même cela ne fonctionnera que pour le premier mot après le strace, donc cela ne s'appliquerait pas directement à votre exemple (où vous avez des options intermédiaires).  Mais si vous définissez

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

puis

my_strace rm ramesh

sera traité comme

strace -ff -e trace=file rm -i ramesh
G-Man dit «Réintègre Monica»
la source
2

Pas d'alias ici

Supposons que nous ayons la définition d'alias alias rm='rm -i'dans notre ~/.bashrc. L'alias ajoute l'option d'invite avant de supprimer chaque fichier:

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

Ce n'est pas la faute de stracene pas avoir utilisé l'alias:
cela n'a rien à voir avec les alias.

Dans la commande

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

Les mots rmet ne ./filesont que des arguments pour strace pour l'instant - le shell ne peut pas développer l'alias rm, car il ne peut pas savoir que strace utilisera ces arguments comme commande plus tard.

En général, les alias de commande ne peuvent être utilisés que là où les commandes peuvent l'être.

Les alias sont une fonctionnalité du shell et stracen'utilisent pas du tout de shell lorsqu'il appelle la commande à partir de la ligne de commande. Il utilise à la exec()place, avec les commandes et les arguments de sa propre ligne de commande.

À l'intérieur de strace, la commande sera appelée avec quelque chose de similaire à exec("rm", "file"), et exec()trouvera /bin/rmdans PATH - sans utiliser de shell.

Shell explicite

Maintenant, pourquoi ne pas inclure un shell dans la stracecommande?

$ 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 ... ça n'a pas marché. rmvient de supprimer le fichier, sans l' -iinvite.

Alias ​​interactifs

Les alias ne sont normalement activés que dans des shells interactifs, des lignes de commande réelles dans un terminal.
Avec notre exemple d'alias, il est facile de comprendre pourquoi cela a du sens: si l' rm -ialias était développé à l'intérieur de scripts shell, il se bloquerait au premier rmavec personne là-bas pour appuyer y.

Les alias sont contrôlés par l'option shell expand_aliases. Nous pourrions définir l'option avec bash +O expand_aliases -c .... Mais cela ne suffit pas, car le shell non interactif ne lira pas non plus ~/.bashrc. Cela signifie que notre alias est non seulement désactivé par l'option, mais également pas défini.

Faire semblant d'être interactif

La manière simple de gérer les deux parties consiste à utiliser l'option de ligne de commande -ipour faire en sorte que le shell prétende qu'il est interactif:

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

Enfin, l' -ialias a été utilisé!

Notez que vous n'utiliseriez pas normalement des shells fonctionnant avec l' -ioption de script, même si vous souhaitez avoir vos alias disponibles, par exemple.

Volker Siegel
la source