использование su внутри сценария оболочки


12

Я автоматизирую процесс развертывания и хочу иметь возможность просто вызвать один файл .sh на моей машине, сделать так, чтобы он выполнил мою сборку и загрузить .zip на сервер, а затем сделать кучу вещей на сервере. Одна из вещей, которые мне нужно сделать, требует, чтобы я был root. Итак, что я хочу сделать, это:

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

Это вообще возможно?


+1 хороший вопрос. Общая проблема.
gMale

Ответы:


15

Вы рассматривали sudo без пароля вместо этого?


1
Это подход, который я использовал в прошлом. Вы можете ограничить sudo требуемыми командами (запускать / останавливать службу), ограничивая права пользователя именно тем, что вам нужно. Это все еще кажется неуклюжим, но работает.
Марк

Это на самом деле то, что я в конечном итоге делал ...
cmcculloh

5

Вместо su используйте sudo с набором NOPASSWD в sudoers для соответствующих команд. Вы хотите, чтобы разрешенный набор команд был максимально ограничен. Вызывать запуск скрипта для корневых команд может быть самым чистым способом, и гораздо проще сделать его безопасным, если вы не знакомы с синтаксисом файла sudoer. Для команд / сценариев, которые требуют полной загрузки среды, sudo su - -c commandработает, хотя может быть излишним.



3

Вы можете передать команду в качестве аргумента SSH, чтобы просто запустить эту команду на сервере и затем выйти:

ssh user@host "command to run"

Это также работает для списка нескольких команд:

ssh user@host "command1; command2; command3"

Или в качестве альтернативы:

ssh user@host "
        command1
        command2
        command3
"

Как уже указывали другие пользователи, при запуске suна сервере будет запущена новая оболочка вместо выполнения последующих команд в сценарии от имени пользователя root. Что вам нужно сделать, это использовать либо sudoили su -c, и принудительно назначить TTY SSH с -tкоммутатором (требуется, если вам нужно ввести пароль root):

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

Подводя итог, можно сказать, что одним из способов достижения того, что вы хотите сделать, будет:

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

Поскольку, sudoкак правило, запоминает уровень авторизации на несколько минут, прежде чем снова запрашивать пароль пользователя root, простое добавление sudoко всем командам, которые необходимо выполнить от имени пользователя root, является, вероятно, самым простым способом запуска команд от имени пользователя root на сервере. Добавление NOPASSWDправила для вашего пользователя /etc/sudoersсделает этот процесс еще более плавным.

Надеюсь, это поможет :-)


Если вам нужна дополнительная информация о добавлении этого NOPASSWDправила, проверьте примеры в нижней части man sudoers. Кроме того, не забудьте использовать visudoпри редактировании вашего sudoersфайла, чтобы избежать поломки!
Джабирали

Я не могу заставить команду su - -c работать. Как бы я предоставил пароль для su?
cmcculloh

Если вы решите использовать su -cвместо sudo, вы должны запустить SSH с -tфлагом - вам будет предложено ввести пароль root на сервере при выполнении команды. Предоставление пароля непосредственно suв качестве аргумента командной строки не поддерживается (насколько я знаю) и не рекомендуется - поскольку простое ps -ef | grep suраскрывает все переданные аргументы su, включая любой пароль, предоставленный из командной строки ...
jabirali

Что касается того, как вы вызываете su -cчерез SSH: ssh -t user@host 'su -lc "<br /> echo this is a test <br /> echo this is another test<br /> "<br />'
Джабирали

Замените <br />вышеприведенное на новые строки в вашем скрипте. Не по теме: Можете ли вы добавить новые строки в комментарии ServerFault? Это было бы весьма полезно при публикации фрагментов кода ...
jabirali

2

Нет. Даже если вы получите пароль su, вам все равно придется иметь дело с тем фактом, что suоткроется новая оболочка, а это означает, что ваши дальнейшие команды не будут переданы ей. Вам нужно будет написать сценарий для корневых операций вместе с исполняемым файлом помощника, который может вызывать его с соответствующими привилегиями.


2
Большинство команд su принимают опцию -c, которая принимает в качестве аргумента команду (и) для выполнения. Я согласен, что сценарий на самом сервере, вероятно, лучше, чем отправка всех cmds через ssh.
Аарон Буш

1

Напишите сценарий ожидания. Я знаю, что вы уже нашли ответ на этот вопрос, но это может быть полезно, если вам нужно войти на группу серверов, которые требуют интерактивного ввода пароля.

Это язык, основанный на TCL, поэтому он может быть немного странным по сравнению с простыми старыми сценариями оболочки. Но он управляет автоматизацией ввода текста и, как вы уже догадались, «ожидает» определенные биты вывода перед вводом любого вида автоматического ввода пароля или повышения привилегий.

Вот хорошая ссылка в качестве руководства: http://bash.cyberciti.biz/security/expect-ssh-login-script/

На случай, если сайт отключится:

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

Я знаю, что это немного поздно, но я бы лично использовал Net :: SSH :: Expect, доступный на CPAN.

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


Expect действительно хорош во многих из этих случаев, если вы не можете использовать обычные сценарии ssh / bash. Тем не менее, он также быстро становится неуклюжим и заставляет вас предполагать, «что вы найдете» на удаленном конце. Если вы можете изменить целевую систему или вообще повлиять на ее поведение, я бы рекомендовал сначала попробовать другой маршрут. Хороший момент, чтобы поднять это здесь, хотя.
Theuni

0

Вы можете использовать 'ssh example.com su -lc "$ cmd"'.

Когда команда содержит опции, вам нужно заключить их в кавычки, иначе «su» может их съесть («su: неверная опция -« A »).

ssh -AX -tt example.com 'su -lc "tmux new-session -A"'
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.