Выполнение заданий от имени другого пользователя

#node.js #unix #ubuntu #forever #setuid

#node.js #unix #ubuntu #навсегда #setuid

Вопрос:

Обычно мы можем выполнять задания от имени другого пользователя sudo -u <user> <cmd> . Однако в случае процесса forever мы должны поступить таким образом:

 exec su -s /bin/sh -c 'exec "$0" "$@"' username -- /path/to/command [parameters...]
  

Ссылка:https://superuser.com/questions/213416/running-upstart-jobs-as-unprivileged-users

Чем это отличается? Что это значит? Кроме того:

 su -s /bin/bash -c bash username -- /path/to/command [parameters...]
  

похоже, не работает!

Ответ №1:

Первый:

 exec su -s /bin/sh -c 'exec "$0" "$@"' username -- /path/to/command [parameters]
  

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

  • exec su -s sh
    заменяет процесс, вызывающий эту команду, на su, запуская оболочку sh
  • -c 'exec "$0" "$@"'
    при вызове командной оболочки sh exec команда и параметры передаются после -- ( $0 это первый параметр в командной строке, после -- , $@ это все, что после этого)

Конечный продукт этого выполняется, /path/to/command как если бы он был вызван непосредственно из username указанной команды; в результате чего дерево процессов выглядит как:

 su [as root] -> /path/to/command [as username]
  

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

 upstart_launcher [as root] -> su [as root] -> sh [as username] -> /path/to/command [as username]
  

(Я не знаю, как будет выглядеть процесс upstart_launcher на этом этапе; у меня нет системы с upstart, чтобы проверить это; но процесс останется)

Теперь важным элементом этого является то, что он просто вызывает exec /path/to/command [arguments…] , как если бы он был введен подобным образом из командной строки.

Когда мы сравниваем это со второй командной строкой, большая часть происходящего похожа, но не совсем одинакова:

 su -s /bin/bash -c bash username -- /path/to/command [parameters...]
  

Почему это не работает? Ну, вы попросили его сделать что-то другое; в данном случае; вы просите его выполнить команду bash из командной строки bash .

Поскольку вы не передали в $0 или $@ -- , все, что после -c , игнорируется, потому что это не передается в в для вызываемой оболочки.

Примеры работы с exec и без exec

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

пропуск всех исполнителей ( su -s /bin/sh -c '"$0" "$@"' proxy -- pstree -aApl ):

 bash,1
  `-bash,1014
      `-su,1017 -s /bin/sh -c "$0" "$@" proxy -- pstree -aApl
          `-sh,1018 -c "$0" "$@" pstree -aApl
              `-pstree,1019 -aApl
  

Добавление внутреннего исполнителя ( su -s /bin/sh -c 'exec "$0" "$@"' proxy -- pstree -aApl ) — обратите внимание на отсутствие второго уровня sh :

 bash,1
  `-bash,1014
      `-su,1020 -s /bin/sh -c exec "$0" "$@" proxy -- pstree -aApl
          `-pstree,1021 -aApl
  

Добавление внутреннего и внешнего exec ( exec su -s /bin/sh -c 'exec "$0" "$@"' proxy -- pstree -aApl ) — обратите внимание на отсутствующий внешний уровень bash и тот факт, что 1014 pid совпадает с pid, который присутствовал в предыдущем вызове bash:

 bash,1
  `-su,1014 -s /bin/sh -c exec "$0" "$@" proxy -- pstree -aApl
      `-pstree,1022 -aApl
  

Комментарии:

1. Спасибо за ваш ответ. 1. Можете ли вы рассказать мне идею высокого уровня, почему это используется (я вижу пример exec, заменяющий текущий процесс) и 2. Почему sudo -u <user-id> cmd здесь не работает. В моем случае я запускаю команду, sudo su -s <my-app-id> forever list которая всегда работает с my-app-id в командной строке?

2. 1. su является более «стандартным», чем sudo; обычно вы найдете su в системах по умолчанию, в то время как sudo является дополнительным компонентом. su считается поддерживаемым оболочкой «правильным способом» изменения идентификатора пользователя запускаемой команды. Форма, которая была предоставлена в примере, была простым шаблоном. Вы просто вводите имя пользователя, а также команду и параметры после -- , и это работает для любой команды, которую вы, возможно, захотите запустить 2. Конфигурация sudo по умолчанию в современных системах заключается в том, чтобы требовать псевдотерминал, прежде чем он заработает, и вещи, запущенные из launchd / upstart / init, не будут иметь терминала.