Oto zmodyfikowana wersja odpowiedzi Willie Wheeler, która przesyła pliki przez tar, ale obsługuje także przekazywanie hasła do sudo na zdalnym hoście.
(stty -echo; read passwd; stty echo; echo $passwd; tar -cz foo.*) \
| ssh remote_host "sudo -S bash -c \"tar -C /var/www/ -xz; echo\""
Odrobina dodatkowej magii tutaj to opcja -S sudo. Ze strony podręcznika sudo:
-S, --stdin Napisz monit o błędzie standardowym i odczytaj hasło ze standardowego wejścia zamiast korzystać z urządzenia końcowego. Hasło musi poprzedzać znak nowej linii.
Teraz tak naprawdę chcemy, aby wyjście tar zostało przesłane do ssh, co przekieruje standardowe wejście ssh na standardowe wyjście tar, usuwając wszelkie sposoby przekazywania hasła do sudo z interaktywnego terminalu. (Możemy użyć funkcji sudo ASKPASS na odległym końcu, ale to inna historia.) Możemy dostać hasło do sudo, przechwytując je z wyprzedzeniem i przygotowując je do wyjścia tar, wykonując te operacje w podpowłoce i przesyłając dane wyjściowe podpowłoka w ssh. Ma to tę dodatkową zaletę, że nie pozostawia zmiennej środowiskowej zawierającej nasze hasło wiszące w interaktywnej powłoce.
Zauważysz, że nie wykonałem polecenia „czytaj” z opcją -p, aby wydrukować monit. Wynika to z faktu, że zapytanie o hasło z sudo jest wygodnie przekazywane z powrotem do stderr naszej interaktywnej powłoki przez ssh. Możesz się zastanawiać "jak działa sudo, biorąc pod uwagę, że działa ono w ssh po prawej stronie naszej rury?" Kiedy wykonujemy wiele poleceń i przesyłamy dane wyjściowe jednego do drugiego, powłoka nadrzędna (w tym przypadku powłoka interaktywna) wykonuje każde polecenie w sekwencji natychmiast po wykonaniu poprzedniego. Gdy każde polecenie za potokiem jest wykonywane, powłoka nadrzędna dołącza (przekierowuje) wyjście standardowej strony lewej do standardowej strony prawej. Dane wyjściowe stają się następnie danymi wejściowymi, gdy przechodzą przez procesy.
$ (stty -echo; read passwd; stty echo; echo $passwd; tar -cz foo.*) | ssh
remote_host "sudo -S bash -c \"tar -C /var/www/ -xz; echo\""
[sudo] password for bruce:
[1]+ Stopped ( stty -echo; read passwd; stty echo; echo
$passwd; tar -cz foo.* ) | ssh remote_host "sudo -S bash -c \"tar -C
/var/www/ -xz; echo\""
$ pstree -lap $$
bash,7168
├─bash,7969
├─pstree,7972 -lap 7168
└─ssh,7970 remote_host sudo -S bash -c "tar -C /var/www/ -xz; echo"`
Nasza interaktywna powłoka to PID 7168, nasza podpowłoka to PID 7969, a nasz proces ssh to PID 7970.
Jedyną wadą jest to, że read zaakceptuje dane wejściowe, zanim sudo zdąży odesłać swój monit. W przypadku szybkiego połączenia i szybkiego zdalnego hosta nie zauważysz tego, ale możesz to zrobić, jeśli jedno z nich jest wolne. Każde opóźnienie nie wpłynie na możliwość wprowadzenia monitu; może pojawić się po rozpoczęciu pisania.
Uwaga Po prostu dodałem wpis pliku hosta dla „remote_Host” do mojego komputera lokalnego w celu pokazu.