Передача нескольких файлов через стандартный ввод (через ssh)

Здравствуйте, ребята я решил проблему так:

# su - zimbra

$ zmlocalconfig -e proxy_server_names_hash_max_size=4096
$ zmlocalconfig -e proxy_server_names_hash_bucket_size=512

$ zmproxyctl start
15
03.06.2019, 18:31
6 ответов

Если вы можете установить прослушиватель 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
5
27.01.2020, 19:49

ОБНОВЛЕНИЕ:На самом деле это не работает, ssh имеет очень четкое представление о том, что означают stdin и stdout/stderr, и на самом деле не позволяет узурпировать stderr для чтения из него. Я удалю этот ответ через несколько дней, так как он не работает. Спасибо за очень интересное обсуждение!!!


К сожалению, нет хорошего способа сделать это напрямую, так как sshклиент будет передавать на сервер только три файловых дескриптора (stdin, stdoutи stderr), и у него нет условий для передачи дополнительные файловые дескрипторы (, которые были бы полезны для этого конкретного варианта использования.)

(Также обратите внимание, что в протоколе SSH предусмотрена возможность передачи дополнительных файловых дескрипторов, только клиент sshне реализует способ использования этой функции. Теоретически, расширения клиента с помощью патча будет достаточно, чтобы открыть эту функцию.)

Один хакерский способ добиться того, что вы ищете, состоит в том, чтобы использовать файловый дескриптор 2 (stderrфайловый дескриптор )для передачи второго файла. Что-то вроде:

$ ssh remote.name \
      /path/to/program -a /dev/stdin -b /dev/stderr \
      <file1.txt 2<file2.txt

Это должно работать, просто может возникнуть проблема, если programпопытается записать в stderr. Вы можете обойти это, повторно -жонглируя файловыми дескрипторами на удаленном конце перед запуском программы. Вы можете переместить file2.txtв дескриптор файла 3 и повторно -открыть stderr для зеркалирования stdout:

$ ssh remote.name \
      /path/to/program -a /dev/stdin -b /dev/fd/3 \
      '3<&2' '2>&1' \
      <file1.txt 2<file2.txt
-1
27.01.2020, 19:49

Если файлы, переданные в качестве аргументов вашей программе, являются текстовыми файлами, и вы можете управлять их содержимым (вы знаете строку, которая не встречается внутри них ), вы можете использовать здесь несколько -] документы:

{
    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чем-то, что не встречается в каждом из файлов соответственно.

19
27.01.2020, 19:49

Возможно, это не совсем то, что вам нужно... Но, может быть, стоит отправить архив через канал, открытый ssh?

Вы сказали, что:

I'm not allowed to store files on the host.

Возможно, у вас нет доступного для записи домашнего каталога или другого удобного места для хранения файлов в течение длительного времени, но я бы сказал, что маловероятно, что у вас нет доступного для записи каталога, даже если временный tmpfsкоторый будет быть доступным только для вашего конкретного соединения.

Многим программам (и даже подпрограммам libc )требуется перезаписываемый /tmp, так что весьма вероятно, что он будет доступен вам.

Затем вы можете использовать сценарий, который распаковывает архив во временный каталог, запускает вашу программу и очищает ее через 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таким образом, чтобы tar-архив использовался как единственный вход и распаковывался в память. Например, если program— это скрипт Python, то с помощью встроенного модуля -в tarfileможно легко добиться чего-то подобного.

14
27.01.2020, 19:49

Если вам разрешено перенаправлять порты через 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 -.

В целом, это не так уж и хорошо, --лучшее знание точной системы/оболочек/конфигурации/разрешений (, которые вы не предоставили, )может позволить найти более разумные решения.

1
27.01.2020, 19:49

В комментарии было установлено, что /tmpдоступен для записи, поэтому просто предварительно скопируйте один из файлов:

scp -p file2.txt host.name:/tmp/
ssh host.name "/path/to/program -a /dev/stdin -b /tmp/file2.txt && rm /tmp/file2.txt" < file1.txt

Это также очищает скопированный файл после успешного запуска (измените &&на ;, если вы хотите удалить его независимо от успеха, но затем обратите внимание, что вы потеряете значение выхода ).


Если это неприемлемо, я предлагаю поработать с /path/to/programили оболочкой для него, которая может отделить два файла от одного входного потока, такого как:

awk 'FNR == 1 && NR > 1 { printf "%c%c%c", 28, 28, 28 } 1' file1.txt file2.txt \
  | ssh host.name /path/to/tweaked_program

Здесь используется разделитель информации ASCII четыре(разделитель файлов, FS )и он утроен, чтобы минимизировать вероятность совпадения двоичного файла с этой строкой. Затем ваш tweaked_programразделит ввод с учетом разделителя, а затем будет работать с двумя сохраненными файлами как с переменными.

Конечно, если вы используете язык с библиотеками для работы с архивами, более безопасным и чистым подходом было бы просто передать tarв такой код через sshвот так:

tar -zpc file1.txt file2.txt |ssh host.name /path/to/tweaked_program

И ваш tweaked_programбудет распаковывать и открывать архив, сохранять каждый файл в другую переменную, а затем запускать исходную логику programдля переменных.

2
27.01.2020, 19:49

Теги

Похожие вопросы