Как использовать su для выполнения остальной части сценария bash как этого пользователя?

Я написал сценарий, который берет в качестве аргумента строку, которая представляет собой конкатенацию имени пользователя и проекта. Сценарий должен переключать (su) на имя пользователя, cd на конкретный каталог, основанный на строке проекта.

Я в основном хочу:

su $USERNAME; cd /home/$USERNAME/$PROJECT; svn update; 

Проблема в том, что когда я делаю su … он просто ждет там. Это имеет смысл, поскольку stream выполнения перешел к переключению на пользователя. Как только я выхожу, все остальные выполняются, но это не работает по желанию.

Я добавил su к команде svn, но команда не удалась (т.е. она не обновляла svn в желаемой директории).

Как написать скрипт, который позволяет пользователю переключать пользователя и вызывать svn (между прочим)?

Хитрость заключается в использовании команды «sudo» вместо «su»,

Возможно, вам придется добавить это

 username1 ALL=(username2) NOPASSWD: /path/to/svn 

в файл / etc / sudoers

и измените свой сценарий на:

 sudo -u username2 -H sh -c "cd /home/$USERNAME/$PROJECT; svn update" 

Где username2 – это пользователь, которому вы хотите запустить команду SVN, а userername1 – это пользователь, выполняющий скрипт.

Если вам нужно несколько пользователей для запуска этого скрипта, используйте имя %groupname вместо имени пользователя1

Гораздо проще: используйте sudo для запуска оболочки и используйте heredoc для подачи команд.

 #!/bin/bash whoami sudo -u someuser bash << EOF echo "In" whoami EOF echo "Out" whoami 

(ответ первоначально на SuperUser )

Для выполнения остальных или части скрипта под другим пользователем используйте следующий скрипт:

 #!/bin/sh id exec sudo -u transmission /bin/sh - << eof id eof 

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

 su -c "cd /home/$USERNAME/$PROJECT ; svn update" -m "$USERNAME" 

Вот еще один подход, который был более удобным в моем случае (я просто хотел сбросить права 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" ... 

Вместо этого используйте 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 

Вас могут попросить ввести пароль этого пользователя, но только один раз.

Невозможно изменить пользователя в сценарии оболочки. Обходные пути, использующие 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'); 

Это сработало для меня

Я отделил свое «обеспечение» от моего «запуска».

  # 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 & 

Вдохновленный идеей от @ 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 выполняются для инициализированной среды.

Давайте будем гением компьютера.