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

StackOverflow https://stackoverflow.com/questions/1988249

Вопрос

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

Я в принципе хочу сделать:

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

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

Я добавил 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, а username1 — это пользователь, запускающий скрипт.

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

Другие советы

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

#!/usr/bin/env bash
whoami
sudo -i -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" -- "$@"
  # 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 &

Вдохновленный идеей из @МарСофт но я изменил строки следующим образом:

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top