Verwenden von su in einem Shell-Skript


12

Ich automatisiere einen Bereitstellungsprozess und möchte nur eine .sh-Datei auf meinem Computer aufrufen, meinen Build ausführen und die .zip-Datei auf den Server hochladen und dann einige Dinge auf dem Server erledigen können. Eines der Dinge, die ich tun muss, erfordert, dass ich root bin. Also, was ich tun möchte, ist Folgendes:

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

Ist das überhaupt möglich?


+1 gute Frage. häufiges Problem.
gMale

Antworten:


15

Haben Sie stattdessen ein Sudo ohne Passwort in Betracht gezogen?


1
Dies ist der Ansatz, den ich in der Vergangenheit verwendet habe. Sie können sudo auf die erforderlichen Befehle beschränken (den Dienst starten / stoppen) und die Berechtigungen des Benutzers auf genau das beschränken, was Sie benötigen. Es fühlt sich immer noch klobig an, aber es funktioniert.
Mark

Dies ist eigentlich, was ich getan habe ...
cmcculloh

5

Verwenden Sie statt su sudo mit dem in sudoers festgelegten NOPASSWD für die entsprechenden Befehle. Sie sollten den zulässigen Befehlssatz so gering wie möglich halten. Das Ausführen eines Skripts für die root-Befehle ist möglicherweise die sauberste und mit Abstand einfachste Methode, um die Sicherheit zu gewährleisten, wenn Sie mit der Syntax von sudoer-Dateien nicht vertraut sind. Bei Befehlen / Skripten, für die die vollständige Umgebung geladen werden muss, sudo su - -c commandfunktioniert dies, obwohl dies möglicherweise zu viel bedeutet.



3

Sie können einen Befehl als Argument an SSH übergeben, um diesen Befehl nur auf dem Server auszuführen, und dann Folgendes beenden:

ssh user@host "command to run"

Dies funktioniert auch für eine Liste mit mehreren Befehlen:

ssh user@host "command1; command2; command3"

Oder alternativ:

ssh user@host "
        command1
        command2
        command3
"

Wie bereits von anderen Benutzern erwähnt, wird beim Ausführen suauf dem Server eine neue Shell gestartet, anstatt nachfolgende Befehle im Skript als root auszuführen. Sie müssen entweder sudooder verwenden su -cund die TTY-Zuweisung zu SSH mit dem -tSwitch erzwingen (erforderlich, wenn Sie das root-Passwort eingeben müssen):

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

Alles in allem wäre eine Möglichkeit, das zu erreichen, was Sie tun möchten:

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

Da Sie sich in der sudoRegel einige Minuten lang an die Berechtigungsstufe erinnern, bevor Sie erneut nach dem Root-Kennwort gefragt werden sudo, ist es wahrscheinlich die einfachste Methode, Befehle als Root auf dem Server auszuführen, wenn Sie alle Befehle voranstellen , die Sie als Root ausführen müssen. Hinzufügen einer NOPASSWDRegel für Ihren Benutzer in/etc/sudoers würde den Prozess noch reibungsloser gestalten.

Ich hoffe das hilft :-)


Wenn Sie weitere Informationen zum Hinzufügen dieser NOPASSWDRegel benötigen , lesen Sie die Beispiele unten in man sudoers. Denken Sie auch daran, visudobeim Bearbeiten Ihrer sudoersDatei zu verwenden, um Beschädigungen zu vermeiden!
Jabirali

Ich kann den Befehl su -c nicht zum Laufen bringen. Wie würde ich das Passwort für su angeben?
Cmcculloh

Wenn Sie su -canstelle von verwenden sudo, sollten Sie SSH mit dem -tFlag ausführen. Wenn der Befehl ausgeführt wird, werden Sie zur Eingabe des Root-Kennworts auf dem Server aufgefordert. Ein Passwort Providing direkt suals Argument Befehlszeile wird weder unterstützt (soweit ich weiß), noch empfohlen - da ein einfache ps -ef | grep sualle Argumente offenbart weitergegeben suvon der Kommandozeile jeden Passwort, einschließlich zur Verfügung gestellt ...
jabirali

Wie Sie su -cüber SSH aufrufen : ssh -t user@host 'su -lc "<br /> echo this is a test <br /> echo this is another test<br /> "<br />'
jabirali

Ersetzen Sie das <br />Obige durch Zeilenumbrüche in Ihrem Skript. Off-Topic: Können Sie ServerFault-Kommentaren neue Zeilen hinzufügen? Das wäre sehr nützlich, wenn Sie Code-Schnipsel veröffentlichen ...
jabirali

2

Nein. Auch wenn Sie das Passwort dafür haben su, müssen Sie sich mit der Tatsache befassen, dass sueine neue Shell geöffnet wird, was bedeutet, dass Ihre weiteren Befehle nicht an diese Shell weitergeleitet werden. Sie müssen ein Skript für die Root-Operationen zusammen mit einer ausführbaren Hilfsprogrammdatei schreiben, die es mit den entsprechenden Berechtigungen aufrufen kann.


2
Die meisten su-Befehle akzeptieren die Option -c, die die auszuführenden Befehle als Argument verwendet. Ich bin damit einverstanden, dass ein Skript auf dem Server wahrscheinlich am besten ist, wenn nicht alle Befehle über ssh gesendet werden.
Aaron Bush

1

Schreiben Sie ein Expect-Skript. Ich weiß, dass Sie bereits eine Antwort darauf gefunden haben, aber dies kann hilfreich sein, wenn Sie sich bei einer Reihe von Servern anmelden müssen, für die eine interaktive Kennworteingabe erforderlich ist.

Es ist eine Sprache, die auf TCL basiert, daher ist es im Vergleich zu einfachen alten Shell-Skripten vielleicht etwas seltsam. Es übernimmt jedoch die Automatisierung der Texteingabe und "erwartet", wie Sie vermutet haben, bestimmte Ausgabefelder, bevor eine Art automatisierte Kennworteingabe oder eine Eskalation von Berechtigungen vorgenommen wird.

Hier ist ein guter Link als Leitfaden: http://bash.cyberciti.biz/security/expect-ssh-login-script/

Nur für den Fall, dass die Website ausfällt:

#!/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

Ich weiß, dass dies etwas spät ist, aber ich würde persönlich Net :: SSH :: Expect verwenden, das bei CPAN erhältlich ist.

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


Expect ist in vielen Fällen sehr hilfreich, wenn Sie kein reguläres ssh / bash-Skript verwenden können. Es wird jedoch auch sehr schnell klobig und lässt Sie davon ausgehen, "was auch immer Sie finden" auf der Remote-Seite. Wenn Sie das Zielsystem oder Einfluss ändern können , wie es sich verhält überhaupt würde ich empfehlen , zunächst einen anderen Weg zu versuchen. Ein guter Punkt, um es hier zu erwähnen.
Theuni

0

Sie können 'ssh example.com su -lc "$ cmd"' verwenden.

Wenn der Befehl Optionen enthält, müssen Sie ihn in Anführungszeichen setzen, andernfalls frisst "su" sie möglicherweise ("su: ungültige Option - 'A').

ssh -AX -tt example.com 'su -lc "tmux new-session -A"'
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.