Orijinal kullanıcıyı birden çok sudo ve su komutuyla nasıl bulursunuz?


93

Sudo veya su aracılığıyla bir komut dosyası çalıştırırken, orijinal kullanıcıyı almak istiyorum. Bu, birden fazla sudoveya subirbiri içine girmeden ve özellikle gerçekleşmelidir sudo su -.

Yanıtlar:


136

Sonuçlar:

Başka hiçbir yöntem garanti edilmediğinden who am i | awk '{print $1}'VEYA kullanın logname.

Kendi olarak giriş yaptınız:

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>

Normal 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 ]#

sudo su -; 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$

1
Bu durumda kullanabilirsinizwho | awk '{print $1}'
SiegeX

2
... oturum açan tek kişi sizseniz (ve yalnızca bir kez).
sonraki duyuruya kadar duraklatıldı.

9
tek ihtiyacınız olan 2 argüman: who am iile aynı who smells bad. Ayrıca, yalnızca STDINbir TTY ile ilişkilendirilmişse çalışır . Yani çalıştırırsan echo "hello" | who am iişe yaramaz.
tylerl

1
echo "hello" | who am iKomut dosyanız terminalin olmadığı bir ortamda çalışmadığı sürece normal şekilde çalışmazsınız . O zaman who am içalışmayan hatayı görebilirsiniz çünkü okunamayan stdin ile ilgili bir tür problem vardır, bu durumda who am istdin gereksinimini karşılamak için çaresizlikten veri içinde borulama yapmayı deneyebilirsiniz . tylerl, o yoldan zaten geçtiğini ve kanal çalışmayacağını çünkü stdin'in hem okunabilir hem de bir TTY ile ilişkili olması gerektiğini belirtiyor.
Edwin Buck

4
@even True, olabildiğince az yapılandırma gerektirmesini istesem de, lognameşimdi kullanıyorum , ki işe yarıyor, nerede who am içalışmıyor.
Bart van Heukelom

18

Mükemmel bir cevap yok . Kullanıcı kimliklerini değiştirdiğinizde, orijinal kullanıcı kimliği genellikle korunmaz, bu nedenle bilgiler kaybolur. Gibi bazı programlar, lognameve who -monlar bağlı olan terminali görmek için kontrol yazarlardan uygulamak stdinve daha sonra bu terminalde kaydedilir hangi kullanıcı bakın.

Bu çözüm genellikle işe yarar, ancak kusursuz değildir ve kesinlikle güvenli kabul edilmemelidir. Örneğin who, aşağıdaki çıktıların çıktığını düşünün :

tom     pts/0        2011-07-03 19:18 (1.2.3.4)
joe     pts/1        2011-07-03 19:10 (5.6.7.8)

tomsuRoot almak için kullanılır ve programınızı çalıştırır. Yeniden STDINyönlendirilmezse, benzeri bir program lognameçıktı alır tom. Yönlendirilmişse (örneğin bir dosyadan):

logname < /some/file

no login nameGirdi uçbirim olmadığı için sonuç " " olur. Yine de daha ilginç olanı, kullanıcının farklı bir oturum açmış kullanıcı gibi görünebilmesidir. Joe pts / 1'de oturum açtığından, Tom koşarak onun gibi davranabilir

logname < /dev/pts1

Şimdi, joekomutu Tom çalıştıran kişi olmasına rağmen diyor . Başka bir deyişle, bu mekanizmayı herhangi bir güvenlik rolünde kullanırsanız, delisiniz.


2
Komut dosyasını kendiniz çalıştırıyorsanız (kullanılan komutların kanıtladığı gibi), sorun güvenlik değildir. Öyleyse, sudo erişimine sahip oldukları için çok daha fazla sorununuz var. Kişi sadece senaryoyu kopyalayabilir ve istediği şekilde değiştirebilir. Bu, bir komut dosyasında kullanmak üzere giriş yapılan adı almanın bir yoludur. Yoksa söylediğin şeyle ilgili bir şeyi mi özlüyorum?
evan

1
@evan: Sudo erişimine sahip olmak, dosyaların üzerine yazma yeteneği anlamına gelmez.
Flimzy

@Flimzy Hangi durumda root bir dosyanın üzerine yazma yeteneğine sahip değildir?
evan

1
@evan: Açıkçası, sudo erişiminiz size bir kabuğa veya dosyaların üzerine yazabilecek başka bir komuta erişim izni vermediğinde.
Flimzy

@evan sudo erişimi her zaman (çoğu yönetici durumunda olmamalıdır) toplam kök erişimi değildir. Yapılandırılabilir kısıtlanmış yürütme bağlamları kümesidir.
DylanYoung

8

Bu, kshHP-UX üzerine yazdığım bir işlev. BashLinux'ta nasıl çalışacağını bilmiyorum . Buradaki fikir, sudosürecin orijinal kullanıcı olarak çalışması ve alt süreçlerin hedef kullanıcı olmasıdır. Ana süreçler arasında geri dönerek, orijinal sürecin kullanıcısını bulabiliriz.

#
# 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
}

Asıl sorunun uzun zaman öncesine ait olduğunu biliyorum ama insanlar (benim gibi) hala soruyorlar ve burası çözümü koymak için iyi bir yer gibi görünüyordu.


5

Kullanıcının oturum açma adını almak için logname (1) kullanmaya ne dersiniz?


logname(1)çalışmıyor ama işe yarıyor logname- yukarıdaki sonuçları ekliyor
evan

başlangıçta denedim $LOGNAMEama bu işe yaramadı. Yukarıdaki sonuçlara da eklendi.
evan

lognameHala tty gerektiriyor mu ? Testlerimle her zaman geçer. (Belki yanlış bir şey yapıyorum.) Linux 8.26 coreutils ile çalıştırıyorum.
simohe

Günlük adım (GNU coreutils) 8.28 on her zaman "logname: oturum açma adı yok" (Ubuntu 18.04.2)
döndürür


2

user1683793'ün findUser () işlevi bash, NSS kitaplıklarında depolanan kullanıcı adlarını da döndürmek için taşındı ve genişletildi.

#!/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"

Bilginize: Bu işlev (ve temel aldığı işlev), birbirinin içine yerleştirilmiş sudo tarafından oluşturulan birden çok kabukta geri dönmeyecek.
asdfghjkl

2

geri dönme ve bir kullanıcı listesi verme

user1683793'ün cevabına göre

TTY dışı işlemleri dışlayarak, oturum açma işleminin başlatıcısı olarak kökü atlıyorum. Bazı durumlarda bunun çok fazla dışlayacağından emin değilim

#!/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
}

lognameveya who am iözellikle de uzun listelerde bana istenen cevap vermedi su user1, su user2, su user3,...

Asıl sorunun uzun zaman öncesine ait olduğunu biliyorum ama insanlar (benim gibi) hala soruyorlar ve burası çözümü koymak için iyi bir yer gibi görünüyordu.


2

PS'yi birden çok kez aramaya alternatif: bir pstree araması yapın

pstree -lu -s $$ | grep --max-count=1 -o '([^)]*)' | head -n 1

çıktı (çift olarak oturum açıldığında): (evan)

pstree argümanları:

  • -l: uzun çizgiler (kısaltılmıyor)
  • -u: kullanıcı (userName) olarak değiştiğinde göster
  • -s $$: bu sürecin ebeveynlerini göster

İlk kullanıcı değişikliğini (giriş olan) grep -ove ile alın head.

sınırlama: komut herhangi bir küme parantezi içermeyebilir ()(normalde değildir)


pstree -lu -s $$ | head -n1 | sed -e 's / [^ (] * (([^)] *)). * / \ 1 /'
Alexx Roche

0

Sistemleri çalıştıran günü systemd-logind, systemd API bu bilgi sağlar . Bu bilgilere bir kabuk komut dosyasından erişmek istiyorsanız, bunun gibi bir şey kullanmanız gerekir:

$ loginctl session-status \
  | (read session_id ignored; loginctl show-session -p User $session_id)
User=1000

session-statusVe show-ssessionsistem komutları loginctlkanıtlar olmaksızın farklı davranışa sahip: session-statusGeçerli oturumu kullanır, ancak show-ssessionyöneticisi kullanır. Bununla birlikte, show-sessionmakine tarafından okunabilir çıktısı nedeniyle komut dosyası kullanımı için kullanılması tercih edilir. Bu nedenle iki çağrıya loginctlihtiyaç vardır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.