Jak wykonać zdalne polecenie i przekazać plik lokalny jako dane wejściowe?

22

Czy można to zrobić:

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

Oznacza to, że chcę wykonać polecenie zdalne przy użyciu pliku lokalnego w jednym kroku, bez uprzedniego scpskopiowania pliku.

jsj
źródło
Jest to możliwe, jeśli komputer zdalny ma
podłączenie

Odpowiedzi:

23

Przegapiłeś tylko jeden symbol =)

ssh user@socket command < /path/to/file/on/local/machine
pośpiech
źródło
Oczywiście! Zastanawiam się, dlaczego nie rozważałem przekierowania wejścia przez ssh ?!
jsj
Co jeśli zdalne polecenie może tylko pobrać argument pliku, a nie odczytać ze standardowego wejścia?
iruvar
@ChandraRavoori w takim przypadku musisz go skopiować scpwcześniej.
pędzi
4
@ChandraRavoori Możesz spróbować podać argument pliku /dev/stdinlub -. Może działać lub nie ( /dev/stdinjest plikiem, ale jego szukanie zakończy się niepowodzeniem)
derobert,
1
@derobert i rush, trochę się z tym bawili i odkryli hacky sposób na zrobienie tego za pomocą podstawiania procesów pod bash. Nadal podlega ograniczeniom związanym z wyszukiwaniem i może stać się nieporęczny przy wszystkich dodatkowych ofertach, które będą potrzebne. Przykład poniżej. cat plik testowy | ssh użytkownik @ machine 'bash -c "wc -l <(cat -)"'
iruvar
4

Jednym ze sposobów, który działa niezależnie od polecenia, jest udostępnienie pliku na zdalnym komputerze za pośrednictwem zdalnego systemu plików. Ponieważ masz połączenie SSH:

  1. Załóż tunel zwrotny SSH . Zobacz także SSH łatwo kopiuj plik do systemu lokalnego
  2. Zamontuj drzewo katalogów komputera zawierające plik, który chcesz udostępnić na zdalnym komputerze za pomocą SSHFS . ( Przykład )
Gilles „SO- przestań być zły”
źródło
W każdym razie ten sposób wymaga dodatkowych ruchów przed wykonaniem polecenia.
pędzi
@Gilles: Myślę, że oryginalny tytuł wprowadzał w błąd, a zrozumiałeś jego pytanie na podstawie wprowadzającego w błąd tytułu. O ile mi wiadomo, pomyślał, że tak naprawdę nie chciał działać na lokalnym pliku, ale po prostu przekazał go jako dane wejściowe. (Ale twoja odpowiedź jest niesamowita, jeśli dobrze ją rozumiem! Może powinienem zadać pytanie, na które odpowiedziałeś, tylko po to, aby dać ci miejsce, w którym znajdziesz odpowiedź, gdzie uzyskasz odpowiednie uznanie.) Zredagowałem tytuł pytania aby był zgodny z ciałem i wybraną odpowiedzią.
iconoclast
@iconoclast Nie pamiętam mojego stanu umysłu, kiedy to napisałem, ale zgadzam się z tą odpowiedzią. Wymaga to pewnej konfiguracji, ale ma tę zaletę, że uogólnia poza bezpośredni wymóg na inne przypadki, w których nie wystarczy skopiować danych wejściowych. Wspomniałbym również o przekierowaniu, gdyby ktoś tego nie zrobił. Bardziej ogólne pytanie zostało zadane wielokrotnie w nieco innych formach.
Gilles „SO- przestań być zły”
Okej, chyba źle zrozumiałem twoją odpowiedź. Nie próbowałem tego, ale wywnioskowałem, że skoro tworzysz tunel zwrotny (z hosta zdalnego do lokalnego?) Zezwalasz na modyfikację pliku lokalnego przez maszynę zdalną. Czy tak nie jest?
iconoclast
@iconoclast Tak, pozwala to zdalnej maszynie modyfikować plik lokalny (oprócz umożliwienia mu odczytu, czego wymaga pytanie).
Gilles „SO- przestań być zły”
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

Jako alternatywę dla bashzastępowania procesów <(cat -)lub < <(xargs -0 -n 1000 cat)(patrz poniżej) możesz po prostu użyć xargsi catprzesłać zawartość określonych plików wc -l(która jest bardziej przenośna).

# 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)"'
szczery
źródło