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


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

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

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

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

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

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

9 98

9 ответов:

фокус в том, чтобы использовать команду "sudo" вместо "su"

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

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

в ваш файл/etc / sudoers

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

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

где пользователю имя_пользователя2 является пользователя, которого вы хотите выполнить команду SVN как и имя_пользователя1 является пользователя, запустившего скрипт.

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

гораздо проще: использовать sudo чтобы запустить оболочку и использовать heredoc кормить его команды.

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

(ответ первоначально на суперпользователя)

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

#!/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 вместо

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=
COMMANDARGS="$(printf " %q" "${@}")"
if [ $(whoami) != "$USERNAME" ]; then
  exec sudo -E su $USERNAME -c "/usr/bin/bash -l $COMMAND $COMMANDARGS"
  exit
fi

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

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