Как выполнить удаленную команду и передать в локальный файл в качестве ввода?

22

Можно ли это сделать:

ssh user@socket command /path/to/file/on/local/machine

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

JSJ
источник
Это возможно, если на удаленном компьютере установлено сетевое монтирование родительского каталога файла локального компьютера или если вы перенаправили файл в команду ssh
h3rrmiller

Ответы:

23

Вы пропустили только один символ =)

ssh user@socket command < /path/to/file/on/local/machine
порыв
источник
Конечно! Интересно, почему я не учел перенаправление ввода через ssh ?!
JSJ
Что если удаленная команда может принимать только аргумент файла и не считывать данные из стандартного ввода?
iruvar
@ChandraRavoori в этом случае вам нужно скопировать его scpраньше.
Раш
4
@ChandraRavoori Вы можете попробовать указать аргумент файла /dev/stdinили -. Может или не может работать ( /dev/stdinэто файл, но поиск его не удастся)
Дероберт
1
@derobert и Rush, поэкспериментировали с ним и обнаружили хакерский способ сделать это, используя подстановку процессов в bash. Это все еще является предметом ограничения поиска и может стать громоздким со всеми дополнительными цитатами, которые будут необходимы. Пример следует. кошка test.file | ssh user @ machine 'bash -c "wc -l <(cat -)"'
iruvar
4

Один из способов, который работает независимо от команды, - сделать файл доступным на удаленной машине через удаленную файловую систему. Так как у вас есть соединение SSH:

  1. Установите обратный туннель SSH . Смотрите также SSH легко скопировать файл в локальную систему
  2. Смонтируйте дерево каталогов вашего компьютера, содержащее файл для совместного использования на удаленном компьютере с SSHFS . ( Пример )
Жиль "ТАК - перестань быть злым"
источник
В любом случае этот способ требует дополнительных перемещений перед выполнением команды.
Раш
@ Жиль: Я думаю, что оригинальное название вводило в заблуждение, и вы поняли его вопрос, основываясь на вводящем в заблуждение названии. Насколько я могу судить, подумал, что он на самом деле не хочет , чтобы действовать на локальный файл, а просто передать его в качестве входных данных. (Но ваш ответ поразителен, если я правильно его понимаю! Может, мне стоит задать вопрос, на который вы ответили, просто чтобы дать вам место, где вы сможете получить ответ, за который вы получите должную оценку.) Я отредактировал название вопросов чтобы это соответствовало телу и выбранному ответу.
иконоборчество
@iconoclast Я не помню свое состояние ума, когда я написал это, но я иду на этот ответ. Это требует некоторой настройки, но имеет преимущество, заключающееся в обобщении, выходящем за рамки непосредственных требований, в других случаях, когда недостаточно скопировать ввод. Я бы также упомянул перенаправление, если бы кто-то еще этого не сделал. Более общий вопрос задавался много раз в несколько разных формах.
Жиль "ТАК ... перестать быть злым"
Хорошо, я, должно быть, неправильно понял ваш ответ. Я не пробовал, но сделал вывод, что, поскольку вы устанавливали обратный туннель (от удаленного к локальному хосту?), Вы позволяли удаленному компьютеру изменять локальный файл. Разве это не так?
иконоборчество
@iconoclast Да, это позволяет удаленной машине изменять локальный файл (в дополнение к тому, что он может читать его, что и требуется в вопросе).
Жиль "ТАК - перестань быть злым"
1
# What if remote command can only take a file argument and not read from stdin? (1_CR)
ssh user@socket command < /path/to/file/on/local/machine
...
cat test.file | ssh user@machine 'bash -c "wc -l <(cat -)"'  # 1_CR

В качестве альтернативы bashпроцессу подстановки <(cat -)или < <(xargs -0 -n 1000 cat)(см. Ниже) вы можете просто использовать xargsи catпередать содержимое указанных файлов wc -l(что является более переносимым).

# Assuming that test.file contains file paths each delimited by an ASCII NUL character \0
# and that we are to count all those lines in all those files (provided by test.file).

#find . -type f -print0 > test.file
# test with repeated line count of ~/.bash_history file
for n in {1..1000}; do printf '%s\000' "${HOME}/.bash_history"; done > test.file

# xargs & cat
ssh localhost 'export LC_ALL=C; xargs -0 -n 1000 cat | wc -l' <test.file

# Bash process substitution
cat test.file | ssh localhost 'bash -c "export LC_ALL=C; wc -l < <(xargs -0 -n 1000 cat)"'
откровенный
источник