У меня есть программа на удаленном хосте, выполнение которой мне нужно автоматизировать. Команда выполнения этой программы на той же машине выглядит примерно так:
/path/to/program -a file1.txt -b file2.txt
В этом случае file1.txt
и file2.txt
используются для совершенно разных вещей в программе, поэтому я не могу просто cat
их вместе. Однако в моем случае file1.txt
и file2.txt
, которые я хочу передать в программу, существуют только на моем устройстве, а не на хосте, где мне нужно выполнить программу. Я знаю, что могу передать по крайней мере один файл через SSH, передав его через stdin
:
cat file1.txt | ssh host.name /path/to/program -a /dev/stdin -b file2.txt
но, поскольку мне не разрешено хранить файлы на хосте, мне нужен способ получить file2.txt
и там. Я думаю, это может быть возможно через злоупотребление переменными среды и творческое использование cat
и sed
вместе, но я недостаточно хорошо знаю инструменты, чтобы понять, как я буду использовать их для достижения этого. Это выполнимо, и как?
решение1
Если файлы, указанные в качестве аргументов вашей программы, являются текстовыми файлами и вы можете контролировать их содержимое (знаете строки, которые не встречаются внутри них), вы можете использовать несколько here-документов:
{
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
Вот cat
пример команды, которая принимает имена файлов в качестве аргументов. Вместо этого можно было бы:
echo "/path/to/prog -a /dev/fd/3 3<<'EOT' -b /dev/fd/4 4<<'EOT'
Замените каждый из EOT
них на то, чего нет в каждом из файлов соответственно.
решение2
Возможно, это не совсем то, что вам нужно... Но, может быть, стоит рассмотреть возможность отправки tarball через канал, открытый с помощью ssh?
Вы сказали, что:
Мне не разрешено хранить файлы на хосте.
Возможно, у вас нет доступного для записи домашнего каталога или другого удобного места для долгосрочного хранения файлов, но я бы сказал, что маловероятно, что у вас нет доступного для записи места, даже если это временное место, tmpfs
которое будет доступно только для вашего конкретного подключения.
Многим программам (и даже процедурам libc) требуется доступный для записи файл /tmp
, поэтому весьма вероятно, что он вам будет доступен.
Затем вы можете использовать скрипт, который распакует tarball во временный каталог, запустит вашу программу и очистит ее через SSH-соединение.
Что-то вроде:
$ 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
'
Возможно, потребуется дополнительная осторожность с путями к файлам, и следует учитывать некоторые особые случаи (проверить их), но общий подход должен работать.
Если нет доступного для записи каталога, возможным подходом будет модификация, program
чтобы взять tarball как единственный вход и распаковать его содержимое в память. Например, если program
это скрипт Python, то использование встроенного tarfile
модуля легко сделает что-то вроде этого.
решение3
Если вы можете установить прослушиватель TCP (может быть порт с более высоким номером), то вы можете использовать второй сеанс SSH для установки второго источника входных данных с помощью nc
.
Пример:
На сервере есть такой скрипт ( ~/script.bash
):
#!/usr/bin/env bash
cat "$1" | tr a 1
nc localhost "$2" | tr '[:lower:]' '[:upper:]'
А локально есть вот эти два файла:
$ cat a
aaa
aaa
aaa
$ cat b
bbb
bbb
bbb
Теперь сначала запустите второй источник ( $serv
это сервер):
ssh "$serv" nc -l -p 2222 -q1 <b &
И выполните команду правильно:
$ ssh "$serv" ./script.bash - 2222 <a
111
111
111
BBB
BBB
BBB
[1]+ Done ssh "$serv" nc -l -p 2222 -q1 < b
решение4
Если вам разрешено перенаправлять порты через ssh
и у вас есть доступ к wget
на удаленной машине и к busybox
на локальной машине, вы можете сделать что-то вроде:
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 $!
( cat
в качестве примера используется программа, которая принимает два файловых аргумента).
Важна только возможность переадресации портов через -R
-- вместо http можно использовать другие методы, например, если ваш netcat
поддерживает параметры -d
и -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)
Могут существовать способы замены <(...)
подстановок процессов, если оболочка входа на удаленной машине не похожа на ksh или bash.
В целом, это не так уж и здорово — более глубокие знания о конкретной системе/оболочках/конфигурации/разрешениях (которые вы не предоставили) могли бы позволить принимать более разумные решения.