При запуске сценария через sudo или su я хочу получить исходного пользователя. Это должно происходить независимо от того, несколько sudo
или su
выполняются внутри друг друга и конкретно sudo su -
.
93
Полученные результаты:
Используйте 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>
Нормальный sudo:
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>
sudo su -:
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 ]#
судо су -; su tom:
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}'
who am i
то же, что иwho smells bad
. Кроме того, он работает, только еслиSTDIN
он связан с телетайпом. Так что если вы запустите,echo "hello" | who am i
это просто не сработает.echo "hello" | who am i
нормально, если ваш скрипт не работает в среде, где нет терминала. Затем вы можете увидеть ошибку, котораяwho am i
не работает, потому что существует какая-то проблема с нечитаемым стандартным вводом, и в этом случае вы можете попытаться передать данные по конвейеруwho am i
от отчаяния, чтобы удовлетворить его требования к стандартному вводу. Тайлерл просто отмечает, что он уже прошел этот путь, и канал не будет работать, потому что stdin должен быть как читаемым, так и связанным с TTY.logname
сейчас, что, как оказалось, работает, а гдеwho am i
- нет.Нет идеального ответа. При изменении идентификаторов пользователей исходный идентификатор пользователя обычно не сохраняется, поэтому информация теряется. Некоторые программы, такие как
logname
и,who -m
реализуют взлом, когда они проверяют, какой терминал подключенstdin
, а затем проверяют, какой пользователь вошел в систему на этом терминале.Это решение часто работает, но оно не является надежным и, конечно, не должно считаться безопасным. Например, представьте, что if
who
выводит следующее:tom
используетсяsu
для получения root-прав и запускает вашу программу. ЕслиSTDIN
не перенаправить, тоlogname
выведет программу вродеtom
. Если он перенаправлен (например, из файла) так:Тогда результат будет "
no login name
", поскольку вход не является терминалом. Однако еще более интересным является тот факт, что пользователь может изображать другого пользователя, вошедшего в систему. Поскольку Джо вошел в систему на pts / 1, Том мог притвориться им, запустивТеперь там написано,
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
работает - добавляем результаты выше$LOGNAME
но это не сработало. Также добавлено к результатам выше.logname
прежнему требуется tty? С моими тестами всегда проходит. (Возможно, я что-то не так.) Я запускаю linux с coreutils 8.26.THIS_USER=`pstree -lu -s $$ | grep --max-count=1 -o '([^)]*)' | head -n 1 | sed 's/[()]//g'`
Это единственное, что у меня сработало.
источник
Функция 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"
источник
возвращаясь на велосипеде и предоставляя список пользователей
на основе ответа user1683793
Исключая процессы, не относящиеся к 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 аргументы:
Получите первое изменение пользователя (то есть логин) с помощью
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
.источник