por que strace ignora meu apelido para rm?

8

Eu tenho um aliasconjunto para o meu rmcomando. Se eu executar o aliascomando, é isso que recebo como saída.

alias rm='rm -i'

Agora, quando executo o rmcomando, ele funciona bem como esperado.

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

Agora, eu estava aprendendo sobre as chamadas do sistema que estão sendo chamadas quando executo um comando. Para isso, fiquei sabendo do stracecomando a partir daqui, que lista os arquivos que estão sendo chamados quando executo algum comando. O comando é como abaixo.

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

O comando funciona perfeitamente bem, exceto que ignora meus aliases que eu tenho para o meu rmcomando. Exclui o arquivo sem avisar o usuário.

Então, straceignora aliases como este? Se sim, por que é assim?

EDITAR:

Não tenho certeza, se isso tem algo a ver, mas type -a rmme fornece a saída como,

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

Portanto, /bin/rmneste caso, é por isso que o usuário não é solicitado antes da exclusão?

Ramesh
fonte
3
stracenão ignora aliases, porque isso implicaria que havia algo a ser ignorado em primeiro lugar. Um alias é um recurso do shell. straceé um programa diferente e, dentro stracedo conceito de alias, não existe; portanto, não há nada a ignorar. A API fornecida pelo kernel para a execução de programas também não possui um conceito de aliases; portanto, não há como o shell diferenciar os aliases, mesmo que desejasse.
kasperd
1
Se você quiser straceum alias, precisará stracedo shell, que implementa o alias. Há algumas abordagens que você pode tomar para fazer isso: strace -p $$ &ou strace bashou strace sh -c 'rm ramesh'(a última vontade também ignoram o alias, mas por uma razão completamente diferente.)
kasperd

Respostas:

20

stracenão é executado rm -ipelo mesmo motivo que:

echo rm

não sai rm -i.

Os aliases são um recurso de alguns shells para permitir que algumas strings sejam substituídas automaticamente por outras quando encontradas na posição de comando.

No:

alias foo='whatever'
foo xxx

As conchas expandem isso para:

whatever xxx

e que passa por outra rodada de interpretação, nesse caso levando à execução do whatevercomando.

os aliases são expandidos apenas quando encontrados na posição de comando (como a primeira palavra de uma linha de comando).

zshsuporta aliases globais .

Você poderia fazer:

alias -g rm='rm -i'

Mas você não gostaria, pois isso significaria que:

echo rm

produziria, rm -ipor exemplo.

Stéphane Chazelas
fonte
8

straceusa a PATHvariável de ambiente para localizar o programa a ser rastreado, em vez de executá-lo através do shell (o que atrapalharia a saída). Um alias do shell não é um programa, é um recurso do shell e, portanto, o straceignora.

Correr strace strace rmé bastante esclarecedor, além de ser curiosamente recursivo.

Marca
fonte
5

Um alias é um recurso do seu shell. No entanto, strace executa o comando diretamente (usando execve, provavelmente), o que não envolve o shell. (Se o strace executasse o comando fornecido por meio do shell, a saída do strace conteria todos os syscalls de execução do shell, e não apenas os do processo de interesse.)

Além disso, quando você executa strace rm ramesh, o shell interativo não tenta substituir seu alias nos argumentos a serem rastreados, porque isso seria terrivelmente confuso para todos. O shell apenas expande aliases que aparecem na primeira posição em uma linha de comando.

Greg Hewgill
fonte
2

O Strace usa execve c functioncomo find commandNo entanto, find uses exec functionvocê não pode usar aliases, built-in shell commandetc.

Você tem que fazer:

strace /bin/rm -i ramesh
PersianGulf
fonte
2

Para aproveitar a resposta de Stéphane Chazelas, se você definir

alias strace="strace "

(com um espaço no final), então o comando

strace rm ramesh

será processado como

strace rm -i ramesh

Mas mesmo isso funcionará apenas para a primeira palavra após a strace, portanto, não se aplicaria diretamente ao seu exemplo (onde você tem opções intermediárias).  Mas se você definir

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

então

my_strace rm ramesh

será processado como

strace -ff -e trace=file rm -i ramesh
G-Man diz que 'restabelece Monica'
fonte
2

Nenhum alias aqui

Vamos assumir que temos a definição de alias alias rm='rm -i'em nossa ~/.bashrc. O alias adiciona a opção de solicitação antes de remover cada arquivo:

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

Não é culpa stracedisso que ele não usou o pseudônimo: não
tem nada a ver com pseudônimos.

No comando

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

As palavras rme ./filesão apenas argumentos para strace por enquanto - o shell não pode expandir o alias rm, porque não pode saber que strace usará esses argumentos como comando posteriormente.

Em geral, os aliases de comando podem ser usados ​​apenas onde os comandos podem estar.

Aliases são um recurso do shell e stracenão usam um shell quando chama o comando na linha de comando. Em exec()vez disso, ele usa os comandos e argumentos de sua própria linha de comando.

Dentro de strace, o comando será chamado com algo semelhante exec("rm", "file")e exec()encontrará/bin/rm no PATH - sem usar um shell.

Shell explícito

Agora, por que não incluir um shell no stracecomando?

$ 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 ... isso não funcionou. rmacabou de excluir o arquivo, sem o -iprompt.

Aliases interativos

Aliases normalmente são ativados apenas em shells interativos, linhas de comando reais em um terminal.
Com o nosso exemplo de alias, é fácil ver por que isso faz sentido: se o rm -ialias fosse expandido dentro de scripts shell, eles seriam interrompidos no início rmsem ninguém lá para pressionar y.

Os aliases são controlados pela opção shell expand_aliases. Poderíamos definir a opção com bash +O expand_aliases -c .... Mas isso não é suficiente, porque o shell não interativo também não lerá~/.bashrc . Isso significa que nosso alias não é apenas desativado pela opção, mas também nem é definido.

Fingindo ser interativo

A maneira mais fácil de lidar com ambas as partes é usar a opção de linha de comando -ipara fazer o shell fingir que é interativo:

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

Finalmente, o -ialias foi usado!

Observe que você normalmente não usaria shells executados com a -iopção de script, mesmo que desejasse ter seus aliases disponíveis, por exemplo.

Volker Siegel
fonte