Passando vários arquivos por stdin (por ssh)

Passando vários arquivos por stdin (por ssh)

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.txte file2.txtsão usados ​​para coisas totalmente diferentes dentro do programa, então não posso apenas catcolocá-los juntos. Porém, no meu caso, o file1.txte file2.txtque 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.txtlá também. Estou pensando que isso pode ser possível através do abuso de variáveis ​​de ambiente e do uso criativo de cate sedem 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 catestá 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 EOTpor 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 tmpfsque 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 programpara usar um tarball como entrada única e descompactar seu conteúdo na memória. Por exemplo, se programfor um script Python, usar o módulo integrado tarfilerealizaria 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 sshe tiver acesso wgetna máquina remota e busyboxna 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 catcomo 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ê netcatsuporta as opções -de -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.

informação relacionada