Tenho um programa em um host remoto, cuja execução preciso automatizar. O comando para executar esse programa, na mesma máquina, é mais ou menos assim:
/path/to/program -a file1.txt -b file2.txt
Neste caso, file1.txt
e file2.txt
são usados para coisas totalmente diferentes dentro do programa, então não posso apenas cat
colocá-los juntos. Porém, no meu caso, o file1.txt
e file2.txt
que desejo passar para o programa existe apenas no meu dispositivo, não no host onde preciso executar o programa. Eu sei que posso alimentar pelo menos um arquivo através do SSH, passando-o por stdin
:
cat file1.txt | ssh host.name /path/to/program -a /dev/stdin -b file2.txt
mas, como não tenho permissão para armazenar arquivos no host, preciso encontrar uma maneira de levá-los para file2.txt
lá também. Estou pensando que isso pode ser possível através do abuso de variáveis de ambiente e do uso criativo de cat
e sed
em conjunto, mas não conheço as ferramentas o suficiente para entender como as usaria para conseguir isso. É factível e como?
Responder1
Se os arquivos fornecidos como argumentos para o seu programa forem arquivos de texto e você for capaz de controlar seu conteúdo (você conhece uma linha que não ocorre dentro deles), poderá usar vários documentos aqui:
{
echo "cat /dev/fd/3 3<<'EOT' /dev/fd/4 4<<'EOT' /dev/fd/5 5<<'EOT'"
cat file1
echo EOT
cat file2
echo EOT
cat file3
echo EOT
} | ssh user@host sh
Aqui cat
está um exemplo de comando que usa nomes de arquivos como argumentos. Poderia ser em vez disso:
echo "/path/to/prog -a /dev/fd/3 3<<'EOT' -b /dev/fd/4 4<<'EOT'
Substitua cada um EOT
por algo que não ocorra em cada um dos arquivos, respectivamente.
Responder2
Talvez não seja exatamente o que você deseja... Mas talvez considere enviar um tarball através do cano aberto pelo ssh?
Você disse aquilo:
Não tenho permissão para armazenar arquivos no host.
É possível que você não tenha um diretório inicial gravável ou outro local conveniente para armazenar arquivos a longo prazo, mas eu diria que é improvável que você não tenha nenhum local gravável, mesmo que seja um local temporário tmpfs
que será disponibilizado apenas para o seu conexão específica.
Muitos programas (e até mesmo rotinas libc) exigem um writable /tmp
, então é muito provável que um esteja disponível para você.
Então você poderia usar um script que irá descompactar o tarball em um diretório temporário, executar seu programa e fazer a limpeza através da conexão ssh.
Algo como:
$ tar cf - file1.txt file2.txt |
ssh host.name '
set -e
tmpdir=$(mktemp -d -t tmp.XXXXXXXXXX)
cleanup () { rm -rf "$tmpdir"; }
trap cleanup EXIT
cd "$tmpdir"
tar xf -
/path/to/program -a file1.txt -b file2.txt
'
Isso pode exigir algum cuidado extra com os caminhos dos arquivos e há alguns casos a serem considerados (testá-los), mas a abordagem geral deve funcionar.
Se nenhum diretório gravável estiver disponível, uma abordagem possível seria modificar program
para usar um tarball como entrada única e descompactar seu conteúdo na memória. Por exemplo, se program
for um script Python, usar o módulo integrado tarfile
realizaria facilmente algo assim.
Responder3
Se você puder definir um ouvinte TCP (pode ser uma porta superior), poderá usar uma segunda sessão SSH para estabelecer a segunda fonte de entrada com nc
.
Exemplo:
Existe este script no servidor ( ~/script.bash
):
#!/usr/bin/env bash
cat "$1" | tr a 1
nc localhost "$2" | tr '[:lower:]' '[:upper:]'
E existem esses dois arquivos localmente:
$ cat a
aaa
aaa
aaa
$ cat b
bbb
bbb
bbb
Agora primeiro inicie a segunda fonte ( $serv
é o servidor):
ssh "$serv" nc -l -p 2222 -q1 <b &
E execute o comando propriamente dito:
$ ssh "$serv" ./script.bash - 2222 <a
111
111
111
BBB
BBB
BBB
[1]+ Done ssh "$serv" nc -l -p 2222 -q1 < b
Responder4
Se você tiver permissão para encaminhar portas ssh
e tiver acesso wget
na máquina remota e busybox
na máquina local, poderá fazer algo como:
mkdir /tmp/test; cd /tmp/test
echo 1st_file > 1st_file
echo 2nd_file > 2nd_file
busybox httpd -f -p 127.0.0.1:11080 &
ssh USER@HOST -R 10080:127.0.0.1:11080 '
cat <(wget -q -O- http://localhost:10080/1st_file) \
<(wget -q -O- http://localhost:10080/2nd_file)
'
kill $!
(usando cat
como exemplo um programa que aceita dois argumentos de arquivo).
Apenas a capacidade de encaminhar portas -R
é essencial - em vez de usar http, você pode usar outros métodos, por exemplo. se você netcat
suporta as opções -d
e -N
:
nc -Nl localhost 11001 < 1st_file &
nc -Nl localhost 11002 < 2nd_file &
ssh USER@HOST -R 10001:localhost:11001 -R 10002:localhost:11002 '
cat <(nc -d localhost 10001) <(nc -d localhost 10002)
Pode haver maneiras de substituir as <(...)
substituições de processos se o shell de login na máquina remota não for do tipo ksh ou bash.
Resumindo, isso não é muito bom - um melhor conhecimento sobre o sistema/shells/config/permissões exatos (que você não forneceu) pode permitir soluções mais inteligentes.