używając su wewnątrz skryptu powłoki


12

Automatyzuję proces wdrażania i chcę mieć możliwość wywołania jednego pliku .sh na moim komputerze, wykonania przez niego kompilacji i przesłania pliku .zip na serwer, a następnie zrobienia wielu rzeczy na serwerze. Jedna z rzeczy, które muszę zrobić, wymaga bycia rootem. Tak więc chcę to zrobić:

ssh user@172.1.1.101 <<END_SCRIPT
su - 
#password... somehow...
#stop jboss
service server_instance stop
#a bunch of stuff here
#all done!
exit
END_SCRIPT

Czy to w ogóle możliwe?


+1 dobre pytanie. powszechny problem.
gMale

Odpowiedzi:


15

Czy zamiast tego zastanawiałeś się nad sudo bez hasła?


1
Takie podejście stosowałem w przeszłości. Możesz ograniczyć sudo do wymaganych poleceń (uruchomić / zatrzymać usługę), ograniczając uprawnienia użytkownika do dokładnie tego, czego potrzebujesz. Nadal czuje się niezręcznie, ale działa.
Mark

Właśnie tak skończyłem ...
cmcculloh,

5

Zamiast su, użyj sudo z ustawionym NOPASSWD w sudoers dla odpowiednich poleceń. Będziesz chciał ograniczyć dozwoloną liczbę poleceń. Uruchamianie skryptu dla poleceń root może być najczystszym i zdecydowanie najłatwiejszym sposobem na zapewnienie bezpieczeństwa, jeśli nie znasz składni plików sudoer. W przypadku poleceń / skryptów, które wymagają załadowania pełnego środowiska, sudo su - -c commanddziała, choć może to być przesada.



3

Możesz przekazać polecenie jako argument do SSH, aby po prostu uruchomić to polecenie na serwerze, a następnie wyjść:

ssh user@host "command to run"

Działa to również w przypadku listy wielu poleceń:

ssh user@host "command1; command2; command3"

Lub alternatywnie:

ssh user@host "
        command1
        command2
        command3
"

Jak zauważyli wcześniej inni użytkownicy, uruchomienie suna serwerze uruchomi nową powłokę zamiast wykonywać kolejne polecenia w skrypcie jako root. Co trzeba zrobić, to użyć jednej sudolub su -ci alokacja siły TTY do SSH z -tprzełącznikiem (wymagany, jeśli trzeba wpisać hasło roota):

ssh -t user@host 'su - -c "command"'
ssh -t user@host 'sudo command'

Podsumowując, jednym ze sposobów osiągnięcia tego, co chcesz zrobić, byłoby:

#!/bin/bash
ssh -t user@172.1.1.101 "
        sudo some_command
        sudo service server_instance stop
        sudo some_other_command
"

Ponieważ sudozazwyczaj zapamiętuje poziom autoryzacji przez kilka minut, zanim ponownie poprosisz o hasło roota, po prostu przygotowując się sudodo wszystkich poleceń, które musisz uruchomić jako root, jest to prawdopodobnie najłatwiejszy sposób uruchamiania poleceń jako root na serwerze. Dodanie NOPASSWDreguły dla użytkownika /etc/sudoerssprawi, że proces będzie jeszcze płynniejszy.

Mam nadzieję, że to pomoże :-)


Jeśli potrzebujesz więcej informacji na temat dodawania tej NOPASSWDreguły, sprawdź przykłady na dole man sudoers. Pamiętaj też, aby używać go visudopodczas edycji sudoerspliku, aby uniknąć uszkodzenia!
jabirali

Nie mogę zmusić polecenia su - -c do działania. Jak mam podać hasło do su?
cmcculloh

Jeśli zdecydujesz się użyć su -czamiast sudo, powinieneś uruchomić SSH z -tflagą - podczas wykonywania polecenia zostaniesz poproszony o podanie hasła roota na serwerze. Zapewnienie hasło bezpośrednio sujako argument wiersza poleceń nie jest ani wspierany (o ile wiem), ani zalecane - od prostego ps -ef | grep suujawnia wszystkie argumenty przekazywane do su, w tym jakiekolwiek hasło podane z linii poleceń ...
jabirali

Co do tego, jak wywołujesz su -cprzez SSH: ssh -t user@host 'su -lc "<br /> echo this is a test <br /> echo this is another test<br /> "<br />'
jabirali

Zastąp <br />powyższe nowymi wierszami w skrypcie. Off-topic: Czy możesz dodawać nowe wiersze do komentarzy ServerFault? Byłoby to bardzo przydatne przy publikowaniu fragmentów kodu ...
jabirali

2

Nie. Nawet jeśli dostaniesz hasło su, nadal musisz poradzić sobie z faktem, że suotworzy się nowa powłoka, co oznacza, że ​​twoje dalsze polecenia nie zostaną jej przekazane. Będziesz musiał napisać skrypt dla operacji root wraz z plikiem wykonywalnym pomocnika, który może go wywołać z odpowiednimi uprawnieniami.


2
Większość poleceń su akceptuje opcję -c, która będzie argumentem do uruchomienia poleceń. Zgadzam się, że skrypt na samym serwerze jest prawdopodobnie najlepszy w porównaniu do wysyłania wszystkich poleceń cmd przez ssh.
Aaron Bush,

1

Napisz skrypt oczekiwań. Wiem, że już znalazłeś odpowiedź na to pytanie, ale może to być pomocne, jeśli musisz zalogować się na kilka serwerów, które wymagają interaktywnego wprowadzania hasła.

Jest to język oparty na TCL, więc może być nieco dziwny w porównaniu do zwykłych starych skryptów powłoki. Ale obsługuje automatyzację wprowadzania tekstu i, jak się domyślacie, „oczekuje” pewnych fragmentów danych wyjściowych przed wprowadzeniem jakiegokolwiek rodzaju automatycznego wprowadzania hasła lub eskalacji uprawnień.

Oto dobry link jako przewodnik: http://bash.cyberciti.biz/security/expect-ssh-login-script/

Na wypadek awarii strony:

#!/usr/bin/expect -f
# Expect script to supply root/admin password for remote ssh server
# and execute command.
# This script needs three argument to(s) connect to remote server:
# password = Password of remote UNIX server, for root user.
# ipaddr = IP Addreess of remote UNIX server, no hostname
# scriptname = Path to remote script which will execute on remote server
# For example:
#  ./sshlogin.exp password 192.168.1.11 who
# ------------------------------------------------------------------------
# Copyright (c) 2004 nixCraft project <http://cyberciti.biz/fb/>
# This script is licensed under GNU GPL version 2.0 or above
# -------------------------------------------------------------------------
# This script is part of nixCraft shell script collection (NSSC)
# Visit http://bash.cyberciti.biz/ for more information.
# ----------------------------------------------------------------------
# set Variables
set password [lrange $argv 0 0]
set ipaddr [lrange $argv 1 1]
set scriptname [lrange $argv 2 2]
set arg1 [lrange $argv 3 3]
set timeout -1
# now connect to remote UNIX box (ipaddr) with given script to execute
spawn ssh root@$ipaddr $scriptname $arg1
match_max 100000
# Look for passwod prompt
expect "*?assword:*"
# Send password aka $password
send -- "$password\r"
# send blank line (\r) to make sure we get back to gui
send -- "\r"
expect eof

1

Wiem, że to trochę za późno, ale osobiście użyłbym Net :: SSH :: Expect, dostępny z CPAN.

http://search.cpan.org/~bnegrao/Net-SSH-Expect-1.09/lib/Net/SSH/Expect.pod


Oczekiwanie jest naprawdę miłe w wielu przypadkach, jeśli nie możesz używać zwykłego skryptu ssh / bash. Jednak szybko staje się naprawdę niezgrabny i sprawia, że ​​zakładasz „wszystko, co znajdziesz” na drugim końcu. Jeśli możesz zmienić system docelowy lub w ogóle wpłynąć na jego zachowanie, zaleciłbym najpierw wypróbowanie innej trasy. Warto jednak przynieść to tutaj.
Theuni

0

Możesz użyć 'ssh example.com su -lc "$ cmd".

Gdy polecenie zawiera opcje, musisz je zacytować, w przeciwnym razie „su” może je zjeść („su: nieprawidłowa opcja -„ A ”).

ssh -AX -tt example.com 'su -lc "tmux new-session -A"'
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.