Você não pode simplesmente ficar sudo
na frente de um comando do shell; é necessário invocar um shell para avaliar esse comando novamente (fazendo coisas como expandir variáveis, abrir arquivos para operadores de redirecionamento etc.). Então isso é
sudo bash -c !!
exceto que isso não funciona muito bem, porque !!
interpola o texto do comando anterior, caracteres especiais e tudo. Você precisa recuperar o texto do comando como uma sequência e passar isso como argumento para sh
. Felizmente, da festa fc
embutido permite que você faça that¹.
sudo bash -c "$(fc -ln -1)"
Ou ainda, para ter certeza de invocar a mesma versão do bash atualmente em execução:
sudo "$BASH" -c "$(fc -ln -1)"
Observe que, como o comando é executado em um processo de shell separado, ele herda variáveis de ambiente (somente as que sudo
preservam, lembre-se), mas não as variáveis internas do shell. As opções de shell (por exemplo kshglob
) e outras configurações também serão iniciadas a partir do padrão.
O mesmo comando² funciona em zsh e ksh, embora o ATT ksh93 exija que o número first
e o last
número sejam passados para fc
³ (que também funciona no bash, zsh e pdksh / mksh):
sudo zsh -c "$(fc -ln -1)"
sudo ksh -c "$(fc -ln -1 -1)"
sudo "$0" -c "$(fc -ln -1 -1)"
Usar $0
para designar o executável do shell em execução funcionará apenas se o shell tiver sido chamado por meio do $ PATH e o $ PATH não tiver sido alterado ou por um caminho absoluto.
Aqui está outro método no zsh que é um pouco mais claro, mas mais longo:
sudo zsh -c $history[$[HISTCMD-1]]
Uma palavra final de aviso: sudo
é para comandos potencialmente perigosos. Não facilite muito o uso!
¹ Há algum espaço em branco extra no começo e a substituição do comando retira novas linhas no final, mas a sintaxe do shell não se importa com isso.
² Não acho que zsh ou ksh tenham algo como o bash $BASH
; $0
só funciona quando é um caminho absoluto ou quando não contém barra e o caminho de busca do comando não foi alterado.
³ é um apelido para no ATT ksh, mas é tão bom quanto. fc
hist