ssh falha ao executar o comando remoto quando executado a partir do script bash do cron - funciona a partir do CLI

5

Eu tenho um script, escrito em bash, que é executado a partir do cron. Uma das primeiras coisas que faz é SSH para um host remoto e recuperar uma lista de arquivos em um diretório. Tudo funciona bem quando executado a partir da linha de comando, mas não do cron.

A seção do script originalmente ficou assim:

FILES=$($SSH_BINARY -i $SSH_KEY $SSH_USER@$REMOTE_HOST "ls $REMOTE_DIRECTORY")
echo "Got files = $FILES"

Eu adicionei uma instrução echo acima dessa linha (mostrada abaixo) para provar que não era um problema de caminho ou variável:

echo "$SSH_BINARY -i $SSH_KEY $SSH_USER@$REMOTE_HOST \"ls $REMOTE_DIRECTORY\""

Se eu pegar a linha de saída resultante e executá-la como o mesmo usuário cron (root), ela funcionará sem problemas.

Pensando que pode ter algo a ver com a atribuição de uma variável, eu modifiquei a linha FILES = para ler (assim, colocando a saída diretamente no meu arquivo last_run_output):

$SSH_BINARY -vv -i $SSH_KEY $SSH_USER@$REMOTE_HOST "ls $REMOTE_DIRECTORY"

A entrada do cron tem esta aparência:

34 * * * * /root/path/to/my/script/get_logs.sh > /root/path/to/last_run_output 2>&1

Então, problemas de PATH, atribuição de variáveis e permissões, comecei a usar sinalizadores de depuração no ssh. Eu corri uma vez a partir da linha de comando, depois do cron, e comparei as saídas. Aqui estão alguns destaques do diff:

O lado - é a tentativa malsucedida, o lado + é a tentativa bem sucedida, execute fora do cron.

@@ -87,9 +77,7 @@
 debug1: Remote: X11 forwarding disabled.
 debug1: Remote: Forced command: /home/sshacs/acssshsink netstorageuser
 debug1: Authentication succeeded (publickey).
-debug2: fd 4 setting O_NONBLOCK
 debug2: fd 5 setting O_NONBLOCK
-debug2: fd 6 setting O_NONBLOCK
 debug1: channel 0: new [client-session]
 debug2: channel 0: send open
 debug1: Entering interactive session.

Não consigo explicar por que esses descritores de arquivos extras são mencionados no debug2 quando executados a partir do cron, mas parece estar relacionado (note que o < = 0 rfd 4 len 0 linha abaixo):

@@ -100,20 +88,672 @@
 debug2: callback done
 debug2: channel 0: open confirm rwindow 0 rmax 32768
 debug2: channel 0: rcvd adjust 131072
-debug2: channel 0: read<=0 rfd 4 len 0
-debug2: channel 0: read failed
-debug2: channel 0: close_read
-debug2: channel 0: input open -> drain
-debug2: channel 0: ibuf empty
-debug2: channel 0: send eof
-debug2: channel 0: input drain -> closed
+  [[ Very large output of the ls command ]]
+debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
 debug2: channel 0: rcvd eof
 debug2: channel 0: output open -> drain
 debug2: channel 0: obuf empty
 debug2: channel 0: close_write
 debug2: channel 0: output drain -> closed
-debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
 debug2: channel 0: rcvd close
+debug2: channel 0: close_read
+debug2: channel 0: input open -> closed
 debug2: channel 0: almost dead
 debug2: channel 0: gc: notify user
 debug2: channel 0: gc: user detached

Qualquer ideia é muito apreciada.

    
por Kyle Smith 19.01.2011 / 18:43

2 respostas

8

Tente adicionar -t -t às suas opções de conexão SSH. Isso vai; forçar um pseudo-terminal a ser alocado.

Multiple -t options force tty allocation, even if ssh has no local tty.

    
por 19.01.2011 / 20:32
1

Você deve depurar seu script ainda mais. Duas coisas para tentar:

Rwrite-o para fazer a saída do arquivo diretamente, em vez do redirecionamento de saída. Ou seja, no script, faça isso:

$SSH_BINARY -i $SSH_KEY $SSH_USER@$REMOTE_HOST "ls $REMOTE_DIRECTORY" > savefile

Execute seu script com bash -x dentro do cron e salve o resultado. Altere a primeira linha do script para #!/bin/bash -x e tente algo como

34 * * * * /root/path/to/my/script/get_logs.sh > script_debug 2>&1

Isso deve ajudá-lo a restringir exatamente o que seu script está fazendo. Eu suspeito de redirecionamento de saída no cron não está funcionando corretamente, neste caso.

Além disso, pergunta idiota: você verificou que o root pode gravar em /root/path/to/last_run_output ? Você verificou que não tem noclobber definido de alguma forma quando o script é executado no cron?

EDIT: novas idéias para solução de problemas com base nos comentários do OP.

Portanto, nenhuma das ideias acima parece estar funcionando. E quanto a salvar o fielist em um arquivo na máquina remota e scp'ing-lo de volta? Isso eliminaria quaisquer problemas estranhos de redirecionamento de cotação ou entrada.

    
por 19.01.2011 / 19:12