Executa vários comandos ssh com diferentes opções

2

Eu tenho um script bash para copiar dois arquivos de uma máquina remota (que não posso controlar), armazenados em um caminho que precisa de root access. Aqui está:

ssh administrator@host "mkdir ${DIR}"
ssh -t administrator@host "sudo su - root -c 'cp /path/for-root-only/data1/${FILENAME} ${DIR}/'"
ssh administrator@host "mv ${DIR}/${FILENAME} ${DIR}/data1-${FILENAME}"
ssh -t administrator@host "sudo su - root -c 'cp /path/for-root-only/data2/${FILENAME} ${DIR}/'"
scp administrator@host:$DIR/{${FILENAME},data1-${FILENAME}} .
ssh administrator@host "rm -r ${DIR}"

O script pede a mesma senha muito tempo. Eu tentei mesclar todos os comandos através deste documento como este para ssh -t :

ssh -t administrator@host << EOF
    mkdir ${DIR}
    sudo su - root -c 'cp /path/for-root-only/data1/${FILENAME} ${DIR}/'
    mv ${DIR}/${FILENAME} ${DIR}/data1-${FILENAME}
    sudo su - root -c 'cp /path/for-root-only/data2/${FILENAME} ${DIR}/'
EOF
scp administrator@host:$DIR/{${FILENAME},data1-${FILENAME}} .
ssh administrator@host "rm -r ${DIR}"

mas há este aviso:

Pseudo-terminal will not be allocated because stdin is not a terminal.

Gostaria de perguntar se existe uma maneira correta de escrever esse script para minimizar o número de solicitações de senha

    
por floatingpurr 19.07.2016 / 13:56

2 respostas

1

Você não precisa fazer isso como um documento AQUI (que é o que o << faz).

Você pode simplesmente fazer ssh remotehost "command1; command2 ; command3"

por exemplo,

% ssh localhost "date ; uptime ; echo hello"
sweh@localhost's password: 
Tue Jul 19 08:07:48 EDT 2016
 08:07:48 up 15 days, 31 min,  3 users,  load average: 0.33, 0.33, 0.40
hello

No entanto, o scp não será facilmente mesclado dessa maneira.

Então você pode querer usar autenticação de chave pública em vez de autenticação por senha (também conhecida como "chaves ssh"). Normalmente, como coisas assim são automatizadas.

    
por 19.07.2016 / 14:08
3

Abra uma conexão SSH uma vez e, em seguida, coloque-a sobre ela. Esse recurso do OpenSSH é chamado de conexões mestre. Consulte Como usar um canal SSH já estabelecido

ssh_control_socket="$(mktemp)"
ssh -o ControlPath="$(ssh_control_socket)" -o ControlMaster=yes -o ControlPersist=yes administrator@host "mkdir ${DIR}"
# other commands using ssh (ssh, scp, rsync, …): pass the same ControlPath option
ssh -o ControlPath="$(ssh_control_socket)" -t administrator@host "…"
rsync -e "ssh -o 'ControlPath=$(ssh_control_socket)'" …
ssh -o ControlPath="$(ssh_control_socket)" administrator@host -O exit
rm -f "$(ssh_control_socket)"

Irritantemente, você precisa passar explicitamente uma opção ControlPath em cada chamada SSH (é o nome de um arquivo usado para comunicação entre cada invocação de ssh e o cliente SSH original que fez a conexão real). Aqui eu passo um nome de soquete explícito para que o script seja autocontido. Se confiar em ~/.ssh/config for aceitável, adicione essa linha ao seu ~/.ssh/config :

ControlPath ~/.ssh/%l_%h_%p_%r.multiplex

Isso faz com que todos os clientes SSH consigam verificar se existe uma conexão existente a ser ligada. O recurso não será realmente usado a menos que haja uma conexão mestre de escuta, você ainda precisa transmitir -o ControlMaster=yes (ou -M para abreviar) na primeira conexão, ou seja, seu script pode ser

# Open the shared connection
ssh -M -o ControlPersist=yes administrator@host :
# … all SSH-relying commands in their basic form, they will go via the shared connection …
# Close the shared connection
ssh -O exit administrator@host
    
por 20.07.2016 / 02:38