Mam skrypt, który łączy się ze zdalnym serwerem i sprawdzam, czy jakiś pakiet jest zainstalowany:
ssh root@server 'bash -s' < myscript.sh
myscript.sh:
OUT=`rpm -qa | grep ntpdate`
if [ "$OUT" != "" ] ; then
echo "ntpdate already installed"
else
yum install $1
fi
Ten przykład można uprościć. Oto, myscript2.sh
który ma ten sam problem:
read -p "Package is not installed. Do you want to install it (y/n)?" choise
Mój problem polega na tym, że bash nie może odczytać moich odpowiedzi interaktywnie.
Czy istnieje sposób na zdalne wykonanie skryptu lokalnego bez utraty możliwości monitowania użytkownika?
Odpowiedzi:
Wypróbuj coś takiego:
Te
-t
siły przydział tty,$(<your_script)
czyta cały plik i w takich przypadkach przekazuje treść jako jeden argumentssh
, który będzie wykonywany przez shell zdalnego użytkownika.Jeśli skrypt potrzebuje parametrów, przekaż je po skrypcie:
Działa dla mnie, nie jestem pewien, czy jest uniwersalny.
źródło
your script
, przy jednoczesnym zachowaniu zalet składni użytej w odpowiedzi? Używaniessh -t yourserver "$(<your_script --some_arg)"
tylko wyników wbash: --some_arg: command not found
.ssh ... $(<script) script_arg1 script_arg2 ...
Problem polega na tym, że
ssh
uruchamia się nieinteraktywna powłoka logowania na zdalnym komputerze. Oczywistym łatwym rozwiązaniem byłoby skopiowanie skryptu na zdalny serwer i uruchomienie go stamtąd:Jeśli kopiowanie nie jest możliwe z jakiegokolwiek powodu, zmodyfikowałbym skrypt, aby najpierw się połączyć i sprawdzić, czy
$1
jest zainstalowany, a następnie ponownie podłączyć i zainstalować w razie potrzeby:źródło
$OUT=$(ssh root@server rpm -qa | grep "$1");
wyjściu, a następnie drugie połączenie zajmie tyle samo czasu, co pierwsze. Czy się mylę?ssh -M foo.example.com sleep 99999999
lubssh -M foo.example.com read <somefifo
jako master i zabij to jawnie (za pomocąkill
lubecho done >somefifo
), gdy skończysz.Oto dobre wytłumaczenie .
Więc dostosowałem skrypt do
i to nie zadziałało.
więc przeniosłem skrypt do pilota, aby uniknąć lokalnego przekierowania na ssh. (Moje polecenia znajdują się w pliku o nazwie f )
To zadziałało. Oto wynik:
Ponieważ @terdon wspomniał, że pierwotnym zamiarem było zdalne uruchamianie lokalnych skryptów, zdalną kopię można zautomatyzować, to tylko jeden przykład w jednym wierszu.
źródło
bash -s < script.sh
OP, tak jak zrobiłeś? Czy możesz zamieścić wyjaśnienie w swojej odpowiedzi zamiast odsyłać do niego?W przeszłości szukałem rozwiązań tego problemu, ale nigdy nie znalazłem rozwiązania w pełni satysfakcjonującego. Przeniesienie do ssh powoduje utratę interaktywności. Dwa połączenia (scp / ssh) są wolniejsze, a plik tymczasowy może pozostać w pobliżu. Cały skrypt w wierszu poleceń często kończy się ucieczką z piekła.
Ostatnio spotkałem się z tym, że rozmiar bufora wiersza poleceń jest zwykle dość duży ('getconf ARG_MAX> 2 MB, gdzie szukałem). I to sprawiło, że pomyślałem o tym, jak mogę to wykorzystać i złagodzić problem ucieczki.
Wynik to:
lub używając tutaj dokumentu i kota:
Rozwinęłem ten pomysł, aby stworzyć w pełni działający przykładowy skrypt BASH,
sshx
który może uruchamiać dowolne skrypty (nie tylko BASH), w których argumentami mogą być również lokalne pliki wejściowe, za pośrednictwem ssh. Zobacz tutaj .źródło
"
znaków, które trzeba będzie uciec. A także jest ograniczony do skryptów BASH. Moje rozwiązanie to ogólny przypadek dowolnej zawartości skryptu dowolnego zainstalowanego języka skryptowego. Ponadto w sshx dalej demonstruję szeregowanie plików argumentów, co jest całkiem sprytne.echo "$(cat my_script | base64)" | base64 --decode
wygląd jest równoważny (-ish)cat my_script | base64 | base64 --decode
, co wygląda bardzo podobnie do braku op.echo "ARG1=$1, USER=$USER, END"
. a)$ ssh host "$(<my_bash)" foo
->ARG1=, USER=user, END foo
. b)$ ssh host bash "<(echo $(cat my_bash|base64) | base64 --decode)" foo
->ARG1=foo, USER=user, END
. Tutaj (a) działa skutecznie:bash -c $'#!/bin/bash\necho "ARG1=$1, USER=$USER, END" foo'
lub coś podobnego. Zauważ, że arg nie działa. Gdzie (b) jest uruchomiony:bash <(echo IyEvY...5EIgo= | base64 --decode) foo
. (2) Użyłem base64 jako kodowania transportowego.