При запуске скрипта через sudo или su я хочу получить исходного пользователя. Это должно происходить независимо от нескольких sudo
или su
прогонов друг в друге и, в частности, sudo su -
.
Как найти исходного пользователя с помощью нескольких команд sudo и su?
Ответы (10)
Полученные результаты:
Используйте who am i | awk '{print $1}'
ИЛИ logname
, так как другие методы не гарантируются.
Зашел под своим именем:
evan> echo $USER
evan
evan> echo $SUDO_USER
evan> echo $LOGNAME
evan
evan> whoami
evan
evan> who am i | awk '{print $1}'
evan
evan> logname
evan
evan>
Обычное судо:
evan> sudo -s
root> echo $USER
root
root> echo $SUDO_USER
evan
root> echo $LOGNAME
root
root> whoami
root
root> who am i | awk '{print $1}'
evan
root> logname
evan
root>
судо су - :
evan> sudo su -
[root ]# echo $USER
root
[root ]# echo $SUDO_USER
[root ]# echo $LOGNAME
root
[root ]# whoami
root
[root ]# who am i | awk '{print $1}'
evan
[root ]# logname
evan
[root ]#
судо су -; су том:
evan> sudo su -
[root ]# su tom
tom$ echo $USER
tom
tom$ echo $SUDO_USER
tom$ echo $LOGNAME
tom
tom$ whoami
tom
tom$ who am i | awk '{print $1}'
evan
tom$ logname
evan
tom$
who | awk '{print $1}'
- person SiegeX; 04.01.2011
who am i
совпадает с who smells bad
. Кроме того, это работает, только если STDIN
связан с TTY. Поэтому, если вы запустите echo "hello" | who am i
, это просто не сработает.
- person tylerl; 04.07.2011
echo "hello" | who am i
из скрипта??
- person evan; 04.07.2011
echo "hello" | who am i
нормально, если бы ваш скрипт не работал в среде, где нет терминала. Затем вы можете увидеть ошибку, что who am i
не работает, потому что есть какая-то проблема с нечитаемым стандартным вводом, и в этом случае вы можете попробовать передать данные в who am i
из отчаяния, чтобы удовлетворить его требования к стандартному вводу. tylerl просто отмечает, что он уже прошел этот путь, и канал не будет работать, потому что стандартный ввод должен быть доступен для чтения и связан с TTY.
- person Edwin Buck; 22.11.2011
ssh [email protected] ./myscript.sh
?
- person Bart van Heukelom; 07.12.2011
ssh [email protected] ./myscript.sh bart
- person evan; 07.12.2011
logname
, который, как оказалось, работает, а who am i
- нет.
- person Bart van Heukelom; 07.12.2011
logname
имеет ту же проблему, что и @tylerl в отношении who am i
: он работает, только если STDIN является TTY. К счастью, это не должно быть проблемой в практических случаях. Другой вариант — stat -c %U "$(readlink /proc/self/fd/0)"
с той же оговоркой, но я не вижу преимуществ перед тем, чтобы просто придерживаться logname
.
- person Wildcard; 13.11.2018
Не существует идеального ответа. При изменении идентификаторов пользователей исходный идентификатор пользователя обычно не сохраняется, поэтому информация теряется. Некоторые программы, такие как logname
и who -m
, реализуют хак, когда они проверяют, какой терминал подключен к stdin
, а затем проверяют, какой пользователь вошел в систему на этом терминале.
Это решение часто работает, но не является надежным и, конечно, не должно считаться безопасным. Например, представьте, что who
выводит следующее:
tom pts/0 2011-07-03 19:18 (1.2.3.4)
joe pts/1 2011-07-03 19:10 (5.6.7.8)
tom
использовал su
для доступа к root и запускает вашу программу. Если STDIN
не перенаправлено, то программа типа logname
выведет tom
. Если он перенаправлен (например, из файла) следующим образом:
logname < /some/file
Тогда результатом будет "no login name
", так как ввод не является терминалом. Однако еще более интересным является тот факт, что пользователь может выдавать себя за другого вошедшего в систему пользователя. Поскольку Джо вошел в систему на pts/1, Том может притвориться им, запустив
logname < /dev/pts1
Теперь там написано joe
, несмотря на то, что именно Том запустил команду. Другими словами, если вы используете этот механизм в какой-либо роли безопасности, вы сошли с ума.
Это функция ksh
, которую я написал для HP-UX. Я не знаю, как это будет работать с Bash
в Linux. Идея состоит в том, что процесс sudo
работает как исходный пользователь, а дочерние процессы являются целевыми пользователями. Перебирая родительские процессы, мы можем найти пользователя исходного процесса.
#
# The options of ps require UNIX_STD=2003. I am setting it
# in a subshell to avoid having it pollute the parent's namespace.
#
function findUser
{
thisPID=$$
origUser=$(whoami)
thisUser=$origUser
while [ "$thisUser" = "$origUser" ]
do
( export UNIX_STD=2003; ps -p$thisPID -ouser,ppid,pid,comm ) | grep $thisPID | read thisUser myPPid myPid myComm
thisPID=$myPPid
done
if [ "$thisUser" = "root" ]
then
thisUser=$origUser
fi
if [ "$#" -gt "0" ]
then
echo $origUser--$thisUser--$myComm
else
echo $thisUser
fi
return 0
}
Я знаю, что первоначальный вопрос был задан давным-давно, но люди (такие как я) все еще спрашивают, и это выглядело как хорошее место для решения.
Как насчет использования logname(1) для получения логина пользователя?
logname(1)
не работает, а logname
работает — добавление результатов выше
- person evan; 05.01.2011
$LOGNAME
, но это не сработало. Также добавлено к результатам выше.
- person evan; 05.01.2011
logname
телетайп? С моими тестами всегда проходит. (Может быть, я что-то не так.) Я использую Linux с coreutils 8.26.
- person simohe; 23.01.2018
Функция findUser() пользователя user1683793 перенесена на bash
и расширена, чтобы она также возвращала имена пользователей, хранящиеся в библиотеках NSS.
#!/bin/bash
function findUser() {
thisPID=$$
origUser=$(whoami)
thisUser=$origUser
while [ "$thisUser" = "$origUser" ]
do
ARR=($(ps h -p$thisPID -ouser,ppid;))
thisUser="${ARR[0]}"
myPPid="${ARR[1]}"
thisPID=$myPPid
done
getent passwd "$thisUser" | cut -d: -f1
}
user=$(findUser)
echo "logged in: $user"
вернуться назад и дать список пользователей
на основе ответа пользователя 1683793
Исключая процессы без TTY, я пропускаю root как инициатора входа в систему. Я не уверен, что в некоторых случаях это может быть слишком много
#!/bin/ksh
function findUserList
{
typeset userList prevUser thisPID thisUser myPPid myPid myTTY myComm
thisPID=$$ # starting with this process-ID
while [ "$thisPID" != 1 ] # and cycling back to the origin
do
( ps -p$thisPID -ouser,ppid,pid,tty,comm ) | grep $thisPID | read thisUser myPPid myPid myTTY myComm
thisPID=$myPPid
[[ $myComm =~ ^su ]] && continue # su is always run by root -> skip it
[[ $myTTY == '?' ]] && continue # skip what is running somewhere in the background (without a terminal)
if [[ $prevUser != $thisUser ]]; then # we only want the change of user
prevUser="$thisUser" # keep the user for comparing
userList="${userList:+$userList }$thisUser" # and add the new user to the list
fi
#print "$thisPID=$thisUser: $userList -> $thisUser -> $myComm " >&2
done
print "$userList"
return 0
}
logname
или who am i
не дали мне желаемого ответа, особенно в более длинных списках su user1
, su user2
, su user3
, ...
Я знаю, что первоначальный вопрос был задан давным-давно, но люди (такие как я) все еще спрашивают, и это выглядело как хорошее место для решения.
Альтернатива многократному вызову ps: сделайте один вызов pstree
pstree -lu -s $$ | grep --max-count=1 -o '([^)]*)' | head -n 1
вывод (при входе в систему как четный): (evan)
Аргументы pstree:
- -l: длинные строки (без сокращения)
- -u: показывать, когда пользователь меняется как (userName)
- -s $$: показать родителей этого процесса
Получите первое изменение пользователя (которое является логином) с помощью grep -o
и head
.
ограничение: команда не может содержать фигурные скобки ()
(обычно их нет)
В системах с systemd-logind
systemd API предоставляет эту информацию. Если вы хотите получить доступ к этой информации из сценария оболочки, вам нужно использовать что-то вроде этого:
$ loginctl session-status \
| (read session_id ignored; loginctl show-session -p User $session_id)
User=1000
Системные команды session-status
и show-ssession
в loginctl
ведут себя по-разному без аргументов: session-status
использует текущий сеанс, а show-ssession
использует менеджер. Однако использование show-session
предпочтительнее для использования скрипта из-за его машиночитаемого вывода. Вот почему необходимы два вызова loginctl
.
Получить его можно у владельца управляющего терминала. Вот старый код C для утилиты whowasi: http://sivann.gr/software/whowasi.c< /а>