Как использовать su для выполнения остальной части bash script в качестве этого пользователя?
Я написал script, который принимает в качестве аргумента строку, которая является конкатенацией имени пользователя и проекта. Предполагается, что script переключит (su) на имя пользователя, cd на конкретный каталог на основе строки проекта.
Я в основном хочу:
su $USERNAME;
cd /home/$USERNAME/$PROJECT;
svn update;
Проблема в том, что когда я делаю su... он просто ждет там. Это имеет смысл, поскольку поток выполнения перешел к переключению на пользователя. Как только я выхожу, остальные выполняются, но он не работает по желанию.
Я добавил su к команде svn, но команда не удалась (т.е. она не обновляла svn в желаемой директории).
Как написать script, который позволяет пользователю переключать пользователя и вызывать svn (между прочим)?
Ответы
Ответ 1
Хитрость заключается в использовании команды "sudo" вместо "su"
Возможно, вам придется добавить этот
username1 ALL=(username2) NOPASSWD: /path/to/svn
в файл /etc/sudoers
и измените свой script на:
sudo -u username2 -H sh -c "cd /home/$USERNAME/$PROJECT; svn update"
Где username2 является пользователем, которым вы хотите запустить команду SVN, а username1 - это пользователь, выполняющий script.
Если вам нужно несколько пользователей для запуска этого script, используйте %groupname
вместо имени пользователя1
Ответ 2
Намного проще: используйте sudo
для запуска оболочки и используйте heredoc для подачи команд.
#!/bin/bash
whoami
sudo -u someuser bash << EOF
echo "In"
whoami
EOF
echo "Out"
whoami
(ответ изначально на SuperUser)
Ответ 3
Используйте script следующим образом, чтобы выполнить оставшуюся часть или часть script под другим пользователем:
#!/bin/sh
id
exec sudo -u transmission /bin/sh - << eof
id
eof
Ответ 4
Вам нужно выполнить все команды разных пользователей как свои собственные script. Если это только одна или несколько команд, то встроенная строка должна работать. Если у вас много команд, лучше всего переместить их в свой файл.
su -c "cd /home/$USERNAME/$PROJECT ; svn update" -m "$USERNAME"
Ответ 5
Вот еще один подход, который был более удобен в моем случае (я просто хотел отбросить привилегии root и выполнить оставшуюся часть моего скрипта от пользователя с ограниченными правами): вы можете сделать так, чтобы скрипт сам перезапускался от правильного пользователя. Предположим, что он изначально запускается с правами root. Тогда это будет выглядеть так:
#!/bin/bash
if [ $UID -eq 0 ]; then
user=$1
dir=$2
shift 2 # if you need some other parameters
cd "$dir"
exec su "$user" "$0" -- "[email protected]"
# nothing will be executed beyond that line,
# because exec replaces running process with the new one
fi
echo "This will be run from user $UID"
...
Ответ 6
Используйте sudo
вместо
EDIT. Как отметил Дуглас, вы не можете использовать cd
в sudo
, так как это не внешняя команда. Вы должны запустить команды в подоболочке, чтобы сделать работу cd
.
sudo -u $USERNAME -H sh -c "cd ~/$PROJECT; svn update"
sudo -u $USERNAME -H cd ~/$PROJECT
sudo -u $USERNAME svn update
Забастовкa >
Возможно, вас попросят ввести этот пароль пользователя, но только один раз.
Ответ 7
Невозможно изменить пользователя в оболочке script. Обходные пути, использующие sudo, описанные в других ответах, вероятно, являются вашим лучшим выбором.
Если вы достаточно злы, чтобы запускать скрипты perl как root, вы можете сделать это с помощью переменных $< $( $> $)
, которые содержат реальный/эффективный uid/gid, например:
#!/usr/bin/perl -w
$user = shift;
if (!$<) {
$> = getpwnam $user;
$) = getgrnam $user;
} else {
die 'must be root to change uid';
}
system('whoami');
Ответ 8
Это сработало для меня
Я отделил свое "обеспечение" от моего "запуска".
# Configure everything else ready to run
config.vm.provision :shell, path: "provision.sh"
config.vm.provision :shell, path: "start_env.sh", run: "always"
то в моем start_env.sh
#!/usr/bin/env bash
echo "Starting Server Env"
#java -jar /usr/lib/node_modules/selenium-server-standalone-jar/jar/selenium-server-standalone-2.40.0.jar &
#(cd /vagrant_projects/myproj && sudo -u vagrant -H sh -c "nohup npm install 0<&- &>/dev/null &;bower install 0<&- &>/dev/null &")
cd /vagrant_projects/myproj
nohup grunt connect:server:keepalive 0<&- &>/dev/null &
nohup apimocker -c /vagrant_projects/myproj/mock_api_data/config.json 0<&- &>/dev/null &
Ответ 9
Вдохновленный идеей @MarSoft, но я изменил строки следующим образом:
USERNAME='desireduser'
COMMAND=$0
COMMANDARGS="$(printf " %q" "${@}")"
if [ $(whoami) != "$USERNAME" ]; then
exec sudo -E su $USERNAME -c "/usr/bin/bash -l $COMMAND $COMMANDARGS"
exit
fi
Я использовал sudo
чтобы позволить паролю меньше выполнять скрипт. Если вы хотите ввести пароль для пользователя, удалите sudo
. Если вам не нужны переменные окружения, удалите -E
из sudo.
/usr/bin/bash -l
обеспечивает выполнение сценариев profile.d
для инициализированной среды.