Eu tenho um programa em um host remoto, cuja execução eu preciso automatizar. O comando execute esse programa, na mesma máquina, se parece com isso:
/path/to/program -a file1.txt -b file2.txt
Nesse caso, file1.txt
e file2.txt
são usados para coisas completamente diferentes dentro do programa, então não posso apenas cat
juntá-las. No entanto, no meu caso, o file1.txt
e file2.txt
que eu quero passar para o programa existem apenas no meu dispositivo, não no host em que preciso executar o programa. Eu sei que posso alimentar pelo menos um arquivo através do SSH passando-o 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, também preciso de uma maneira de passar file2.txt
por lá. Estou achando que isso pode ser possível através do abuso de variáveis de ambiente e do uso criativo de cat
e sed
juntos, mas não conheço as ferramentas o suficiente para entender como as usaria para fazer isso. É factível e como?
fonte
cat
esed
não é a solução aqui.Respostas:
Se os arquivos fornecidos como argumentos para o seu programa forem arquivos de texto e você puder controlar o conteúdo deles (você conhece uma linha que não ocorre dentro deles), poderá usar vários documentos aqui:
Aqui
cat
está um exemplo de comando que usa nomes de arquivos como argumentos. Pode ser:Substitua cada um
EOT
por algo que não ocorra em cada um dos arquivos, respectivamente.fonte
dash
(/bin/sh
no debian, ubuntu, etc),busybox sh
o/bin/sh
do FreeBSD eyash
não usa arquivos temporários para os documentos aqui. Na verdade, eu testei com um chroot somente leitura. Obviamente, os/dev/fd/
arquivos precisam estar disponíveis - somente em um sistema FreeBSD padrão/dev/fd/0-2
, portantofdescfs
, devem ser montados/dev/fd
.U+001C
é "Information Separator Four" (separador de arquivos, FS) e é ideal para este caso, embora arquivos binários possam utilizá-lo por coincidência. Portanto, eu sugiroEOT="$(printf $'\x1c')"
em conchas avançadas ou entãoEOT="$(awk 'BEGIN{printf"%c",28}')"
para compatibilidade. Você precisará citá-lo quando o colocar no lugar, comoecho "$EOT$EOT$EOT"
(triplicou para diminuir as chances de corresponder a um arquivo binário).tty
comando? A menos que esteja faltando alguma coisa - o que suponho ser possível?Talvez não seja exatamente o que você deseja ... Mas considere enviar um tarball através do cano aberto pelo ssh?
Você disse aquilo:
É 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 um temporário
tmpfs
seja disponibilizado apenas para o seu conexão particular.Muitos programas (e até rotinas de libc) requerem um gravável
/tmp
, portanto é muito provável que um esteja disponível para você.Então você pode usar um script que irá descompactar o tarball em um diretório temporário, executar seu programa e limpar através da conexão ssh.
Algo como:
Isso pode exigir algum cuidado extra com os caminhos dos arquivos e há alguns casos a serem considerados (teste para eles), mas a abordagem geral deve funcionar.
Se nenhum diretório gravável estiver disponível, uma abordagem possível seria modificar
program
para pegar um tarball como entrada única e descompactar seu conteúdo na memória. Por exemplo, seprogram
for um script Python, o uso dotarfile
módulo embutido poderia facilmente realizar algo assim.fonte
/tmp/
e usá-lo diretamente.Se você pode definir um ouvinte TCP (pode ser uma porta mais alta), poderá usar uma segunda sessão SSH para estabelecer a segunda fonte de entrada
nc
.Exemplo:
Existe este script no servidor (
~/script.bash
):E existem esses dois arquivos localmente:
Agora, primeiro inicie a segunda fonte (
$serv
é o servidor):E execute o comando corretamente:
fonte
Foi criado em um comentário que
/tmp
é gravável, tão simplesmente copiar um dos arquivos de antemão:Isso também limpa o arquivo copiado após uma execução bem-sucedida (altere
&&
para a;
se você deseja removê-lo independentemente do sucesso, mas observe que você perderá o valor de saída).Se isso não for aceitável, eu sugeriria mexer com
/path/to/program
um invólucro para separar os dois arquivos de um único fluxo de entrada, como:Isso usa o separador de informações ASCII quatro (separador de arquivos, FS) e o triplicou, para minimizar a chance de um arquivo binário coincidentemente conter essa sequência. Você
tweaked_program
dividiria a entrada, dado o separador, e depois operaria nos dois arquivos salvos como variáveis.Obviamente, se você usa uma linguagem que possui bibliotecas para lidar com tarballs, uma abordagem mais segura e limpa seria simplesmente
tar
inserir esse código dassh
seguinte maneira:E você
tweaked_program
descompactaria e abriria o arquivo morto, salvaria cada arquivo em uma variável diferente e executaria aprogram
lógica do original nas variáveis.fonte
Se você tiver permissão para encaminhar portas
ssh
e tiver acesso àwget
máquina remota e àbusybox
máquina local, poderá fazer algo como:(usando
cat
como um programa de exemplo que recebe dois argumentos de arquivo).Somente a capacidade de encaminhar portas
-R
é essencial - em vez de fazer o http, você pode usar outros métodos, por exemplo. se o seunetcat
suporta as opções-d
e-N
:Pode haver maneiras de substituir as substituições do
<(...)
processo se o shell de login na máquina remota não for do tipo ksh ou bash.Em suma, isso não é muito bom - um melhor conhecimento sobre o sistema exato / shells / config / Permissions (que você não forneceu) pode permitir soluções mais inteligentes.
fonte
UPDATE: Isso realmente não funciona, o ssh tem uma idéia muito definida do que stdin e stdout / stderr significam e não permite realmente que o usurpador stderr o leia. Excluirei esta resposta em alguns dias, pois ela não funciona. Obrigado pela discussão muito interessante !!!
Infelizmente, não há uma ótima maneira de fazer isso diretamente, pois o
ssh
cliente passará apenas os três descritores de arquivo (stdin
,stdout
estderr
) para o servidor e não possui disposições para passar descritores de arquivo adicionais (o que seria útil para esse caso de uso específico). .)(Observe também que o protocolo SSH tem disposições para passar descritores de arquivos adicionais, apenas o
ssh
cliente não implementa uma maneira de usar esse recurso. Teoricamente, estender o cliente com um patch seria suficiente para expor esse recurso.)Uma maneira hacky de realizar o que você está procurando é usar o descritor de arquivo 2 (o
stderr
descritor de arquivo) para passar o segundo arquivo. Algo como:Isso deve funcionar, pois pode causar um problema se
program
tentar gravar no stderr. Você pode contornar isso manipulando novamente os descritores de arquivo na extremidade remota antes de executar o programa. Você pode passarfile2.txt
para o descritor de arquivo 3 e reabrir o stderr para espelhar o stdout:fonte
3<&2
é um operador de shell Bourne e o sshd executa o shell de login do usuário para interpretar o comando enviado pelo cliente)SSH_MSG_CHANNEL_EXTENDED_DATA
mensagens com o tipo definido comoSSH_EXTENDED_DATA_STDERR
. Você pode ler a coisa toda aqui