Eu tenho um sistema no qual só posso fazer login com meu nome de usuário (myuser), mas preciso executar comandos como outro usuário (scriptuser). Até agora, vim com o seguinte para executar os comandos necessários:
ssh -tq myuser@hostname "sudo -u scriptuser bash -c \"ls -al\""
Se, no entanto, quando tento executar um comando mais complexo, [[ -d "/tmp/Some directory" ]] && rm -rf "/tmp/Some directory"
rapidamente encontro problemas com a citação. Não tenho certeza de como poderia passar esse exemplo de comando complexo para bash -c
, quando \"
já delimita os limites do comando que estou passando (e, portanto, não sei como citar o diretório / tmp / Some, que inclui espaços.
Existe uma solução geral que me permita passar qualquer comando, não importa quão complexa / louca seja a citação, ou é algum tipo de limitação que eu alcancei? Existem outras soluções possíveis e talvez mais legíveis?
Respostas:
Um truque que uso às vezes é usar o base64 para codificar os comandos e canalizá-lo para o bash no outro site:
Isso codificará o script, com vírgulas, barras invertidas, aspas e variáveis dentro de uma string segura, e o enviará para o outro servidor. (
-w0
é necessário para desativar a quebra de linha, o que acontece na coluna 76 por padrão). Por outro lado,$(base64 -d)
decodificará o script e alimentará o bash para ser executado.Eu nunca tive nenhum problema com isso, não importa quão complexo o script fosse. Resolve o problema de escapar, porque você não precisa escapar de nada. Ele não cria um arquivo no host remoto e você pode executar scripts muito complicados com facilidade.
fonte
ssh user@remotehost "echo `base64 -w0 script.sh` | base64 -d | sudo bash"
base64 script | ssh remotehost 'base64 -d | sudo bash'
seria suficiente :)Veja a
-tt
opção? Leia ossh(1)
manual.Uma coisa que costumo fazer é usar o vim e usar o
:!cat % | ssh -tt somemachine
truque.fonte
:!cat % | (command)
pode ser feito como:w !(command)
ou:!(command) < %
.ssh -tt
faz com que meu ssh para não terminar após certos comandos são executados (adicionandoexit
no final não ajuda)Acho que a solução mais fácil está na modificação do comentário do @ thanasisk.
Crie um script
scp
na máquina e execute-o.Tenha o
rm
próprio script no início. O shell abriu o arquivo, então ele foi carregado e pode ser removido sem problemas.Ao fazer as coisas nesta ordem (
rm
primeiro, outras coisas em segundo), ele será removido mesmo quando falhar em algum momento.fonte
Você pode usar o
%q
especificador de formatoprintf
para cuidar da variável que está escapando:printf -v
grava a saída em uma variável (neste caso,$cmd_str
). Eu acho que essa é a maneira mais simples de fazer isso. Não há necessidade de transferir nenhum arquivo ou codificar a sequência de comandos (por mais que eu goste do truque).Aqui está um exemplo mais complexo, mostrando que ele também funciona para colchetes e e comercial:
Ainda não testei,
sudo
mas deve ser tão simples quanto:Se desejar, você pode pular uma etapa e evitar a criação da variável intermediária:
Ou até mesmo evite criar uma variável inteiramente:
fonte
Aqui está a maneira "correta" (sintática) de executar algo como isto no bash:
Para uma explicação detalhada de como isso funciona, consulte https://stackoverflow.com/a/21761956/111948
fonte
Você sabe que pode usar
sudo
para fornecer um shell no qual você pode executar comandos como o usuário escolhido?fonte
Você pode definir o script na sua máquina local e, em seguida,
cat
canalizá-lo para a máquina remota:fonte
sudo -u scriptuser
? O heredoc seria utilizável, considerando que eu preciso ter variáveis no script que eu estaria canalizando para a máquina?echo "sudo `cat fileForSsh.txt`" | ssh ...
mas continuo recebendosudo: sorry, you must have a tty to run sudo
./etc/sudoers
arquivo alteradossh -tq user@host "sudo bash -s" < test.sh
Simples e fácil.
fonte
Se você usar um shell Bash suficientemente moderno, poderá colocar seus comandos em uma função e imprimi-la como uma string usando
export -p -f function_name
. O resultado dessa cadeia de caracteres pode conter comandos arbitrários que não precisam necessariamente ser executados como raiz.Um exemplo usando pipes da minha resposta no Unix.SE :
Um exemplo que recupera salva o arquivo para o usuário de login e instala um programa como raiz:
Se você deseja executar o comando inteiro usando
sudo
, você pode usar o seguinte:fonte
Aqui está a minha solução ruim (não realmente testada) para isso:
Você não pode fazer:
O próximo passo é criar um
betterssh
script que já faça isso:fonte
Para aqueles que precisam passar parâmetros para o script, deve ser o seguinte:
fonte
Primeiro, crie um script local e execute-o remotamente usando o seguinte comando:
fonte