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

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

Я в основном хочу сделать:

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

проблема в том, что когда я делаю Су... он просто ждет. Что имеет смысл, так как поток выполнения перешел к переключению на пользователя. Как только я выхожу, остальные вещи выполняются но это работает не так, как хотелось бы.

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

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

9 ответов


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

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


гораздо проще: использовать 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

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

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

вот еще один подход, который был более удобен в моем случае (я просто хотел отказаться от привилегий root и сделать остальную часть моего скрипта от ограниченного пользователя): вы можете перезапустить скрипт от правильного пользователя. Предположим, что он запускается как root изначально. Тогда это будет выглядеть так:

#!/bin/bash
if [ $UID -eq 0 ]; then
  user=
  dir=
  shift 2     # if you need some other parameters
  cd "$dir"
  exec su "$user" "" "$@"
  # 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 вместо

редактировать: как отметил Дуглас, вы не можете использовать 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=
COMMANDARGS="$(printf " %q" "${@}")"
if [ $(whoami) != "$USERNAME" ]; then
  exec sudo -E su $USERNAME -c "/usr/bin/bash -l $COMMAND $COMMANDARGS"
  exit
fi

я использовал sudo разрешить пароль меньше выполнения скрипта. Если вы хотите ввести пароль пользователя, удалить sudo. Если вам не нужны переменные среды, удалите -E С судо.

на /usr/bin/bash -l гарантирует, что profile.d скрипты выполняются для инициализации среды.