por que strace ignora meu alias para rm?

8

Eu tenho um alias definido para o meu comando rm . Se eu executar o comando alias , isso é o que recebo como saída.

alias rm='rm -i'

Agora, quando executo o comando rm , 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 eu tenho que saber sobre o comando strace de aqui 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, exceto que ele ignora meus aliases que tenho no lugar do meu comando rm . Exclui o arquivo sem avisar o usuário.

Então, strace ignora aliases assim? Em caso afirmativo, por que é assim?

EDITAR:

Não tenho certeza se isso tem algo a fazer, mas type -a rm me fornece a saída como

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

Então, é considerado /bin/rm neste caso, e é por isso que o usuário não é solicitado antes da exclusão?

    
por Ramesh 17.09.2014 / 22:06

6 respostas

20

strace não é executado em rm -i pela mesma razão que:

echo rm

não produz rm -i .

Aliases são uma característica de alguns shells para permitir que algumas strings sejam automaticamente substituídas por outras quando encontradas na posição de comando.

Em:

alias foo='whatever'
foo xxx

Os shells expandem isso para:

whatever xxx

e que passa por outra rodada de interpretação, nesse caso, levando a executar o comando whatever .

Os pseudônimos

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

zsh suporta aliases globais .

Você poderia fazer:

alias -g rm='rm -i'

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

echo rm

produziria rm -i , por exemplo.

    
por 17.09.2014 / 22:33
8

strace usa a variável de ambiente PATH para localizar o programa a ser rastreado, em vez de executá-lo através do shell (o que sobrecarregaria a saída). Um alias de shell não é um programa, é um recurso do shell e, portanto, strace o ignora.

A execução de strace strace rm é bastante esclarecedora, além de ser interessante recursiva.

    
por 17.09.2014 / 22:21
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 através do shell, a saída do strace conteria todos os syscalls de execução do shell, e não apenas aqueles do processo de interesse.)

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

    
por 17.09.2014 / 22:18
2

strace usa execve c function , como find command , mas find uses exec function Você não pode usar aliases , built-in shell command ou assim por diante.

Você precisa fazer:

strace /bin/rm -i ramesh
    
por 17.09.2014 / 22:16
2

Para construir 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 o strace , por isso não se aplicaria diretamente ao seu exemplo (onde você tem opções de intervenção). 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
    
por 18.09.2014 / 02:09
2

Nenhum alias aqui

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

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

Não é culpa de strace que ele não tenha usado o alias:
Não tem nada a ver com aliases.

No comando

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

As palavras rm e ./file sã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 mais tarde.

Em geral, os aliases de comando só podem ser usados onde os comandos podem ser.

Aliases são um recurso do shell, e strace não usa um shell quando chama o comando a partir da linha de comando. Ele usa exec() , com os comandos e argumentos de sua própria linha de comando.

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

Shell explícito

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

$ 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. rm acabou de excluir o arquivo, sem o prompt -i .

Apelidos interativos

Os aliases são normalmente habilitados apenas em shells interativos, linhas de comando reais em um terminal.
Com nosso alias de exemplo, é fácil entender por que isso faz sentido: se o rm -i alias fosse expandido dentro de scripts de shell, eles seriam interrompidos no primeiro rm sem ninguém por pressionar y .

Os aliases são controlados pela opção expand_aliases do shell. 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 o nosso alias não é apenas desligado pela opção, mas também não é definido.

Fingindo ser interativo

A maneira fácil de lidar com ambas as partes é usar a opção de linha de comando -i para fazer com que a concha finja que é interativa:

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

Finalmente, o -i alias foi usado!

Observe que você normalmente não usaria shells executando com a opção -i para scripts, mesmo se você quisesse ter seus aliases disponíveis, por exemplo.

    
por 18.09.2014 / 10:23

Tags