Você não pode simplesmente colocar sudo
na frente de um comando shell, você tem que 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, porque !!
interpola o texto do comando anterior, caracteres especiais e todos. Você precisa recuperar o texto do comando como uma string e passar isso como um argumento para sh
. Felizmente, o fc
builtin do bash permite que você faça isso.
sudo bash -c "$(fc -ln -1)"
Ou mesmo, para 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 as variáveis de ambiente (apenas as que sudo
preserva, importa), mas não as variáveis internas do shell. As opções de shell (por exemplo, kshglob
) e outras configurações serão iniciadas a partir do padrão.
O mesmo comando² funciona em zsh e ksh, embora o ATT ksh93 requeira que os números first
e last
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 funciona apenas se o shell tiver sido invocado por meio do $ PATH e se o $ PATH não tiver sido alterado ou por meio de um caminho absoluto.
Aqui está outro método em zsh que é um pouco mais claro, mas mais longo:
sudo zsh -c $history[$[HISTCMD-1]]
Uma última palavra de aviso: sudo
é para comandos potencialmente perigosos. Não seja muito fácil usá-lo!
¹ Há um espaço em branco extra no início e a substituição do comando retira as novas linhas no final, mas a sintaxe do shell não se importa com isso.
² Eu não acho que zsh ou ksh tenham algo como $BASH
do bash; $0
só funciona quando é um caminho absoluto ou quando não contém nenhuma barra e o caminho de pesquisa do comando não foi alterado.
³ fc
é um alias para hist
em ATT ksh, mas isso é bom.