Подтвердить что ты не робот

Как получить каталог $HOME другого пользователя в bash script?

Мне нужно выполнить часть bash script как другого пользователя и внутри этого пользовательского каталога $HOME. Однако я не уверен, как определить эту переменную. Переход к этому пользователю и вызов $HOME не обеспечивают правильное расположение:

# running script as root, but switching to a different user...
su - $different_user
echo $HOME
# returns /root/ but should be /home/myuser

Обновление:

Похоже, проблема связана с тем, что я пытаюсь переключить пользователей в свой script:

$different_user=deploy

# create user
useradd -m -s /bin/bash $different_user

echo "Current user: `whoami`"
# Current user: root

echo "Switching user to $different_user"
# Switching user to deploy

su - $different_user
echo "Current user: `whoami`"
# Current user: root
echo "Current user: `id`"
# Current user: uid=0(root) gid=0(root) groups=0(root)

sudo su $different_user
# Current user: root
# Current user: uid=0(root) gid=0(root) groups=0(root)

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

4b9b3361

Ответ 1

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

В этом случае самым простым решением является использование расширения tilde с интересующим именем пользователя в сочетании с eval (что необходимо, потому что имя пользователя должно быть задано как некотируемый литерал для расширения тильды):

eval echo "~$different_user"    # prints $different_user home dir.

Примечание. обычный оговорки относительно использования eval применяются; в этом случае предполагается, что вы управляете значением $different_user и знаете, что это просто имя пользователя.

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


Примечание:

  • Администраторы по умолчанию и другие пользователи, если они авторизованы через файл sudoers, могут выдавать себя за других пользователей через sudo.
  • Ниже приведена конфигурация по умолчанию sudo - изменение конфигурации может привести к поведению по-другому - см. man sudoers.

базовая форма выполнения команды как другого пользователя:

sudo -H -u someUser someExe [arg1 ...]
  # Example:
sudo -H -u root env  # print the root user environment

Примечание:

  • Если вы не укажете -H, процесс выдачи (процесс, вызванный в контексте указанного пользователя) будет сообщать исходный домашний каталог пользователя в $HOME.
  • Процесс выдачи будет иметь тот же рабочий каталог, что и процесс вызова.
  • Выдающийся процесс выполняет без расширений оболочки в строковых литералах, переданных в качестве аргументов, так как никакая оболочка не участвует в процессе олицетворения (если только someExe не является оболочкой) - разложения вызывающей оболочкой - до перехода к выдающему себя процессу - очевидно, все еще может произойти.

Необязательно, вы можете выполнить выдающийся процесс как или с помощью (n impersonating) оболочки, путем префикса someExe либо с помощью -i , либо -s - не указывая someExe ... создает интерактивную оболочку:

  • -i создает логин для someUser, что подразумевает следующее:

    • someUser Пользовательский профиль оболочки, если он определен, загружен.
    • $HOME указывает на домашний каталог someUser, поэтому не требуется -H (хотя вы все еще можете указать его)
    • Рабочий каталог для олицетворяющей оболочки - это домашний каталог someUser.
  • -s создает оболочку без входа:

    • профиль оболочки не загружен (хотя файлы инициализации для интерактивных оболочек нелогического типа, например, ~/.bashrc)
    • Если вы не укажете -H, процесс выдачи будет сообщать исходный домашний каталог пользователя в $HOME.
    • Выдающаяся оболочка будет иметь тот же рабочий каталог, что и процесс вызова.

Использование оболочки означает, что строковые аргументы, переданные в командной строке, могут быть подвержены расширениям оболочки - см. различия в платформе ниже - с помощью олицетворяющей оболочки (возможно, после первоначального расширения вызывающей оболочкой); сравните следующие две команды (которые используют одинарные кавычки для предотвращения преждевременного расширения вызывающей оболочкой):

  # Run root shell profile, change to root home dir.
sudo -u root -i eval 'echo $SHELL - $USER - $HOME - $PWD'
  # Don't run root shell profile, use current working dir.
  # Note the required -H to define $HOME as root`s home dir.
sudo -u root -H -s eval 'echo $SHELL - $USER - $HOME - $PWD'

Вызывается какая оболочка определяется "переменной среды SHELL, если она установлена, или оболочкой, указанной в passwd (5)" (в соответствии с man sudo). Обратите внимание, что при -s важна вызывающая пользовательская среда, тогда как с -i это олицетворяемый пользовательский интерфейс.

Обратите внимание, что существуют различия в платформе относительно поведения, связанного с оболочкой (с -i или -s):

  • sudo в Linux, по-видимому, принимает только исполняемое имя или встроенное имя в качестве первого аргумента, следующего за -s/-i, тогда как OSX позволяет передавать всю командную строку оболочки; например, OSX принимает непосредственно sudo -u root -s 'echo $SHELL - $USER - $HOME - $PWD' (нет необходимости в eval), тогда как Linux не имеет значения (из sudo 1.8.95p).

  • Старые версии sudo в Linux НЕ применяют расширения оболочки для аргументов, передаваемых оболочке; например, с помощью sudo 1.8.3p1 (например, Ubuntu 12.04), sudo -u root -H -s echo '$HOME' просто отсылает строковый литерал "HOME" вместо расширения ссылки на переменную в контексте пользователя root. По меньшей мере sudo 1.8.9p5 (например, Ubuntu 14.04) это было исправлено. Поэтому, чтобы обеспечить расширение Linux даже с более старыми версиями sudo, передайте всю команду как единственный аргумент eval; например: sudo -u root -H -s eval 'echo $HOME'. (Хотя это не обязательно для OSX, это тоже будет работать.)

  • root переменная $SHELL $SHELL содержит /bin/sh в OSX 10.9, тогда как она находится в /bin/bash на Ubuntu 12.04.

Если процесс олицетворения включает оболочку или нет, в ее окружении будут установлены следующие переменные, отражающие вызывающего пользователя и команду: SUDO_COMMAND, SUDO_USER, SUDO_UID=, SUDO_GID.

См. man sudo и man sudoers для многих других тонкостей.

Совет шляпы для @DavidW и @Andrew для вдохновения.

Ответ 2

В BASH вы можете найти каталог пользователя $HOME, предварительно указав идентификатор входа пользователя в тильду. Например:

$ echo ~bob

Это выведет пользовательский каталог bob $HOME.

Однако вы говорите, что хотите выполнить script как конкретный пользователь. Для этого вам нужно настроить sudo. Эта команда позволяет вам выполнять определенные команды как для определенного пользователя. Например, для выполнения foo в качестве пользователя bob:

$ sudo -i -ubob -sfoo

Это запустит новую оболочку, а -i будет имитировать логин с пользовательской средой по умолчанию и оболочкой (что означает, что команда foo будет выполняться из каталога bob's $HOME`.)

Sudo немного сложна для настройки, и вам нужно быть суперпользователем, чтобы видеть файл дрозд (обычно /etc/sudoers). Однако этот файл обычно имеет несколько примеров, которые вы можете использовать.

В этом файле вы можете указать команды, которые вы укажете, кто может запускать команду, как пользователь, и должен ли этот пользователь вводить свой пароль перед выполнением этой команды. Обычно это значение по умолчанию (потому что оно доказывает, что это пользователь, а не тот, кто пришел, пока пользователь получал Coke.) Однако при запуске оболочки script вы обычно хотите отключить эту функцию.

Ответ 3

Для альтернативного ответа для тех, кто ищет легкий способ просто найти домашний каталог пользователя...

Вместо того, чтобы возиться с su хаками или беспокоиться о накладных расходах на запуск другой оболочки bash, чтобы найти переменную среды $HOME...

Легкий простой запрос Homedir через Bash

Для этого есть команда: getent

getent passwd someuser | cut -f6 -d:

getent может сделать намного больше... просто просмотрите справочную страницу . База данных passwd nsswitch вернет запись пользователя в формате /etc/passwd. Просто разделите его на двоеточие :, чтобы проанализировать поля.

Он должен быть установлен на большинстве Linux-систем (или любой системы, которая использует GNU Lib C (RHEL: glibc-common, Deb: libc-bin)

Ответ 4

В этом случае вам нужна опция -u для sudo. На странице man:

The -u (user) option causes sudo to run the specified command as a user other than root.

Если вам не нужно на самом деле запускать его как его, вы можете перейти в свой домашний каталог с помощью ~<user>. Как и в случае, чтобы перейти в мой домашний каталог, вы должны использовать cd ~chooban.

Ответ 5

Итак, вы хотите:

  • выполнить часть bash script как другого пользователя
  • изменить этот каталог $HOME

Вдохновленный этим ответом, здесь адаптированная версия вашего script:

#!/usr/bin/env bash

different_user=deploy

useradd -m -s /bin/bash "$different_user"

echo "Current user: $(whoami)"
echo "Current directory: $(pwd)"
echo

echo "Switching user to $different_user"
sudo -u "$different_user" -i /bin/bash - <<-'EOF'
    echo "Current user: $(id)"
    echo "Current directory: $(pwd)"
EOF
echo

echo "Switched back to $(whoami)"

different_user_home="$(eval echo ~"$different_user")"
echo "$different_user home directory: $different_user_home"

Когда вы запустите его, вы должны получить следующее:

Current user: root
Current directory: /root

Switching user to deploy
Current user: uid=1003(deploy) gid=1003(deploy) groups=1003(deploy)
Current directory: /home/deploy

Switched back to root
deploy home directory: /home/deploy

Ответ 6

Я тоже искал это, но не хотел выдавать себя за пользователя, чтобы просто получить путь!

user_path=$(grep $username /etc/passwd|cut -f6 -d":");

Теперь в вашем script вы можете обратиться к $user_path, в большинстве случаев это будет /home/username

Предполагается: вы ранее установили $username со значением имени пользователя. Источник: http://www.unix.com/shell-programming-and-scripting/171782-cut-fields-etc-passwd-file-into-variables.html

Ответ 7

Это работает в Linux. Не уверен, как он ведет себя в других * nixes.

  getent passwd "${OTHER_USER}"|cut -d\: -f 6

Ответ 8

Быстро и грязно, и сохраните его в переменной:

USER=somebody
USER_HOME="$(echo -n $(bash -c "cd ~${USER} && pwd"))"

Ответ 9

Я боролся с этим вопросом, потому что я искал способ сделать это в bash script для OS X, поэтому /etc/passwd не может быть и речи, и мой script был предназначен для выполняются как root, поэтому решения, вызывающие eval или bash -c, опасны, поскольку они допускают ввод кода в переменную с указанием имени пользователя.

Вот что я нашел. Он прост и не помещает переменную внутри подоболочки. Однако для этого требуется, чтобы script выполнялся от имени root, поскольку он sudos в указанную учетную запись пользователя.

Предполагая, что $SOMEUSER содержит действительное имя пользователя:

echo "$(sudo -H -u "$SOMEUSER" -s -- "cd ~ && pwd")"

Надеюсь, это поможет кому-то!

Ответ 10

Если пользователь не существует, getent вернет ошибку.

Здесь небольшая функция оболочки, которая не игнорирует код выхода getent:

get_home() {
  local result; result="$(getent passwd "$1")" || return
  echo $result | cut -d : -f 6
}

Вот пример использования:

da_home="$(get_home missing_user)" || {
  echo 'User does NOT exist!'; exit 1
}

# Now do something with $da_home
echo "Home directory is: '$da_home'"