Как написать сценарий оболочки, который запускает некоторые команды как суперпользователь, а некоторые команды не как суперпользователь, без необходимости присматривать за ним?

Я хочу написать сценарий оболочки для автоматизации ряда команд. Проблема в том, что некоторые команды ДОЛЖНЫ выполняться от имени суперпользователя, а некоторые НЕ ДОЛЖНЫ выполняться от имени суперпользователя. То, что я сделал до сих пор, выглядит примерно так:

#!/bin/bash

command1
sudo command2
command3
sudo command4

Проблема в том, что это означает, что кто-то должен дождаться завершения команды 1, прежде чем ему будет предложено ввести пароль, а затем, если команда 3 займет достаточно много времени, ему придется дождаться завершения команды 3. Было бы неплохо, если бы человек мог встать и уйти, а потом вернуться через час и покончить с этим. Например, следующий сценарий имеет эту проблему:

#!/bin/bash

sleep 310
sudo echo "Hi, I'm root"
sleep 310
sudo echo "I'm still root?"

Как я могу сделать так, чтобы пользователь мог просто ввести свой пароль один раз, в самом начале, а затем уйти?

Обновление:

Спасибо за ответы. Я работаю в Mac OS X Lion, запускаю сценарий Стивена П. и получаю другие результаты: (я также добавил $HOME)

pair@abbey scratch$ ./test2.sh
uid is 501
user is pair
username is 
home directory is /Users/pair
pair@abbey scratch$ sudo ./test2.sh 
Password:
uid is 0
user is root
username is root
home directory is /Users/pair

person speedarius    schedule 19.04.2012    source источник


Ответы (4)


Файл sutest

#!/bin/bash
echo "uid is ${UID}"
echo "user is ${USER}"
echo "username is ${USERNAME}"

запустить его: `./sutest' дает мне

uid is 500
user is stephenp
username is stephenp

но использование sudo: sudo ./sutest дает

uid is 0
user is root
username is stephenp

Таким образом, вы сохраняете исходное имя пользователя в $USERNAME при работе от имени sudo. Это приводит к решению, аналогичному тому, что опубликовали другие:

#!/bin/bash
sudo -u ${USERNAME} normal_command_1
root_command_1
root_command_2
sudo -u ${USERNAME} normal_command_2
# etc.

Просто sudo, чтобы вызвать ваш скрипт в первую очередь, он запросит пароль один раз.


Первоначально я написал этот ответ для Linux, который имеет некоторые отличия от OS X.

В OS X (я тестирую это на Mountain Lion 10.8.3) есть переменная окружения SUDO_USER когда вы запускаете sudo, которую можно использовать вместо USERNAME выше, или чтобы быть более кросс- платформе сценарий может проверить, установлен ли SUDO_USER, и использовать его, если это так, или использовать USERNAME, если он установлен.

Изменив оригинальный скрипт для OS X, он становится...

#!/bin/bash
sudo -u ${SUDO_USER} normal_command_1
root_command_1
root_command_2
sudo -u ${SUDO_USER} normal_command_2
# etc.

Первая попытка сделать его кроссплатформенным может быть...

#!/bin/bash
#
# set "THE_USER" to SUDO_USER if that's set,
#  else set it to USERNAME if THAT is set,
#   else set it to the string "unknown"
# should probably then test to see if it's "unknown"
#
THE_USER=${SUDO_USER:-${USERNAME:-unknown}}

sudo -u ${THE_USER} normal_command_1
root_command_1
root_command_2
sudo -u ${THE_USER} normal_command_2
# etc.
person Stephen P    schedule 19.04.2012
comment
Вы также можете создать сценарий оболочки, который принадлежит пользователю root и имеет установленный бит suid, но это может быть опасно, если вы не сделаете это правильно. Каждый раз, когда вы запускаете сценарии оболочки от имени пользователя root, вы можете захотеть использовать trap для обработки сигналов. shelldorado.com/goodcoding/tempfiles.html содержит несколько примеров. - person Stephen P; 19.04.2012
comment
Странно, у меня на самом деле другие результаты. Это в Mac OS X Lion: pair@abbey scratch$ ./test2.sh‹br/› uid is 501‹br/› user is pair‹br/› username is ‹br/› home directory is /Users/pair‹br/› pair@abbey scratch$ sudo ./test2.sh ‹br/› Password:‹br/› uid is 0‹br/› user is root‹ br/› username is root‹br/› home directory is /Users/pair‹br/› pair@abbey scratch$ sudo -u pair ./test2.sh ‹br/› uid is 501‹br/› user is pair‹br/› username is pair‹br/› home directory is /Users/pair‹br/› - person speedarius; 19.04.2012
comment
Извините за форматирование комментария выше; Я обновляю исходный пост сейчас .. - person speedarius; 19.04.2012
comment
В Ubuntu 12.04 или новее вы также хотите использовать ${SUDO_USER}. - person kynan; 24.10.2013
comment
Я на Xubuntu 14.04, и переменная USERNAME не существует, когда я не root. Имеет ли смысл определить это в моем файле .bashrc? Я не понимаю, почему он появляется только тогда, когда я root, а не иначе. Я набрал env | grep USERNAME и ничего не появилось, но когда я набрал sudo env | grep USERNAME, оно появилось как USERNAME=root - person Jesse; 25.04.2014
comment
На самом деле я обнаружил, что переменная среды, которая отражает мое имя пользователя и не меняется при запуске sudo, — это SUDO_USER. Я запустил sudo env | grep jesse, чтобы посмотреть, какие переменные по-прежнему являются моим именем пользователя. - person Jesse; 25.04.2014

Вы должны запустить весь свой скрипт как суперпользователь. Если вы хотите запустить какую-либо команду от имени пользователя без прав суперпользователя, используйте опцию «-u» sudo:

#!/bin/bash

sudo -u username command1
command2
sudo -u username command3
command4

При запуске от имени root sudo не запрашивает пароль.

person Pavel Strakhov    schedule 19.04.2012

Если вы используете это, проверьте также man sudo:

#!/bin/bash

sudo echo "Hi, I'm root"

sudo -u nobody echo "I'm nobody"

sudo -u 1000 touch /test_user
person Sampo Sarrala - codidact.org    schedule 19.04.2012

Что ж, у вас есть несколько вариантов.

Вы можете настроить sudo так, чтобы он не запрашивал пароль. Это не рекомендуется из-за рисков безопасности.

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

Я бы порекомендовал разработать сценарий для запуска от имени пользователя root и отказа от его привилегий, когда они не нужны. Просто используйте его sudo -u someotheruser command для команд, не требующих root.

(Если они должны запускаться специально от имени пользователя, вызывающего скрипт, вы можете заставить скрипт сохранить uid и вызвать второй скрипт через sudo с идентификатором в качестве аргумента, чтобы он знал, кому su ..)

person Mark Reed    schedule 19.04.2012