Почему я не могу использовать 'sudo su' в сценарии оболочки? Как заставить скрипт оболочки работать с sudo автоматически
Я не могу понять, что с этим не так. Когда я запускаю его в терминале и ввожу пароль, ничего не происходит, но если я запускаю каждую команду отдельно в терминале, она работает. Спасибо!
#!/bin/bash
sudo su;
mkdir /opt/D3GO/;
cp `pwd`/D3GO /opt/D3GO/;
cp `pwd`/D3GO.png /opt/D3GO/;
cp `pwd`/D3GO.desktop /usr/share/applications/;
chmod +x /opt/D3GO/D3GO
6 ответов
команда sudo su
запускает интерактивную корневую оболочку, но она не преобразует текущую оболочку в корневую.
идиома, чтобы сделать то, что вы хотите, - это что-то вроде этого (спасибо @CharlesDuffy за дополнительную осторожность):
#check for root
UID=$(id -u)
if [ x$UID != x0 ]
then
#Beware of how you compose the command
printf -v cmd_str '%q ' "" "$@"
exec sudo su -c "$cmd_str"
fi
#I am root
mkdir /opt/D3GO/
#and the rest of your commands
идея состоит в том, чтобы проверить, является ли текущий пользователь root, а если нет, повторите ту же команду с su
sudo su
не является командой, выполняемой в оболочке -- it запускает новую оболочку.
эта новая оболочка больше не запускает ваш скрипт, а старая оболочка, которая и запуск сценария ожидает выхода нового, прежде чем он продолжится.
можно использовать Здесь Документы для перенаправления ввода в интерактивный сценарий оболочки. Оператор <<
- это инструкция для чтения ввода, пока она не найдет строку, содержащую указанный разделитель, как EOF
(конец файла).
sudo su <<EOF
echo "code"
EOF
например
#!/bin/bash
sudo su <<EOF
mkdir /opt/D3GO/
cp `pwd`/D3GO /opt/D3GO/
cp `pwd`/D3GO.png /opt/D3GO/
cp `pwd`/D3GO.desktop /usr/share/applications/
chmod +x /opt/D3GO/D3GO
EOF
на принято отвечать работает, а идиома для сценария, повторно вызывающего себя с sudo
по требованию может быть упрощенный и составила портативный:
[[ $(id -u) -eq 0 ]] || exec sudo /bin/bash -c "$(printf '%q ' "$BASH_SOURCE" "$@")"
используя
[[ ... ]]
вместо[ ... ]
делает эту директивуx
для операндов (или двойного цитирования LHS) ненужно.используя
bash -c
вместоsu -c
для интерпретации реконструированных командная строка делает команду более переносимой, потому что не все платформы поддерживаютsu -c
(например, macOS не делает).на
bash
,$BASH_SOURCE
обычно является более надежным способом ссылки на запущенный скрипт.
при вышеуказанном подходе любые ссылки на переменные или команды / арифметические замены в аргументах неизменно расширяются вызов shell.
если вы вместо вас хотела задержана расширения - так что ссылки на переменные не расширена до sudo
shell запускается в контексте root пользователь-используйте это:
(( __reinvoked )) || exec sudo -s __reinvoked=1 "$BASH_SOURCE" "$@"
обратите внимание, что тогда тебе придется один - цитируйте любые аргументы, содержащие ссылки на переменные или замены команд, для которых они должны быть расширены с задержкой; например,'$USER'
.
обратите внимание на использование переменной среды ad-hoc __reinvoked
для обеспечения re-invocation только один раз (даже если изначально уже вызывается как пользователь root).
здесь скрипт это демонстрирует первую технику:
если не запускается как root, скрипт reinvokes с
sudo -s
, передавая все аргументы через as-is.если ранее не прошел проверку подлинности и все еще в течение периода ожидания,
sudo
предложит для управляющий пароль.
#!/bin/bash
[[ $(id -u) -eq 0 ]] || exec sudo /bin/bash -c "$(printf '%q ' "$BASH_SOURCE" "$@")"
# Print the username and all arguments.
echo "Running as: $(id -un)"
echo "Arguments:"
for arg; do echo " $((++i)): [$arg]"; done
полезный ответ acfreitas показывает "сценарий внутри сценария" техника где здесь-документ используется для предоставления кода оболочки через stdin в sudo su
.
Опять,sudo -s
достаточно и цитирую важен:
sudo -s -H <<'EOF'
echo "$HOME"
EOF
обратите внимание, как открывается здесь-разделитель документов,EOF
в данном случае процитировано для того чтобы предотвратить содержание документа от вперед толкование current shell.
Если вы не цитировали (любую часть) EOF
, $HOME
будет расширяться на current домашний каталог пользователя.
если вы хотите mix вперед и с задержкой расширения, оставьте Открытие здесь-разделитель документа без кавычек и выборочно \
кавычки $
случаях:
sudo -s -H <<EOF
echo "Called by: $USER; root's home dir: $HOME"
EOF
потому что запуск "sudo su" открывает новую оболочку, и команда не возвращается, пока вы не выйдете из этой оболочки. Возможно, разделите скрипт на 2 файла: первый запускает sudo и выполняет этот 2-й скрипт под sudo.
sudo su попытается запустить новую оболочку как root. Как только эта новая оболочка будет открыта, исходный сценарий не будет продолжаться, пока новая оболочка не будет закрыта.
для исправления попробовать:
в shell-скрипт, попробовать:
su <username> -c "my command"
Итак, если пользователь был "userA":
su userA -c "mkdir /opt/D3GO/"
однако, если вы пользователь, например, и вы хотите запустить часть скрипта как root, вам будет предложено пройти.
su root -c "mkdir /opt/D3GO/"
вы также можете обойти это путем просто запуск скрипта с sudo в первую очередь
sudo ./myScript.sh
таким образом, скрипт сохраняет исходного пользователя внутри скрипта, к которому вы можете получить доступ, используя стандартные переменные, такие как ${USERNAME}, ${UID} etc
зависит от того, что работает лучше для вас.