Soru Bash betiğinde farklı kullanıcının $ HOME dizini nasıl alınır?


Bir bash komut dosyasının bir bölümünü farklı bir kullanıcı olarak ve bu kullanıcının içinde çalıştırmam gerekiyor $HOME dizin. Ancak, bu değişkeni nasıl belirleyeceğimi bilmiyorum. Bu kullanıcıya geçme ve arama $HOME doğru konumu sağlamaz:

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

Güncelleştirme:

Sorunun, kullanıcıları komutumda değiştirmeye çalıştığım şekilde olduğu anlaşılıyor:

$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)

Kullanıcıları değiştirmek ve komutları bash komut dosyasında farklı bir kullanıcı olarak çalıştırmanın doğru yolu nedir?


44
2017-12-10 20:35


Menşei


Yerel olarak tanımlanmış bir hesap olduğunu varsayarak, her zaman / etc / passwd'den ayıklayabilirsiniz. - Marc B
su - $different_user yeterli olmalıydı. Oturum açmış olduğunuzdan bile emin misiniz? myuser. Koşmayı dene id doğrulamak için komut. Bazı giriş kabuğu ayarlandı nologin ve en kısa zamanda giriş yaptığınız anda çıkıyor myuser. - anubhava
@anubhava Sorgumu, kullanıcıyı nasıl oluşturduğumu eklemek için güncelledim. esasen: useradd -m -s /bin/bash $different_user. - Andrew
Lütfen cevabıma başka bir göz atın. Tam olarak yapmaya çalıştığınız şeyle eşleşmek için önemli ölçüde değiştirdim. - Michael Kropat


Cevaplar:


Güncelleştirme: Bu sorunun başlığına göre insanlar buraya geliyor gibi görünüyor sadece bir yol arıyorum bulmak farklı bir kullanıcının ev dizini, gerek kalmadan taklit etmek o kullanıcı.

Bu durumda, en basit çözüm kullanmaktır tilde genişlemesi ilgi alanına giren kullanıcı adıyla birlikte eval (gerekli olan, çünkü kullanıcı adı bir belirtilmemiş edebi tilde genişlemenin çalışması için):

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

Not: olağan kullanımı ile ilgili uyarılar eval uygulamak; Bu durumda, varsayım değeri $different_user ve sadece bir kullanıcı adı olduğunu biliyoruz.

Buna karşılık, bu cevabın geri kalanı ile ilgilidir özellikleri alınırken Bir kullanıcı ve performans işlemleri o kullanıcının giriş dizininde.


Not:

  • Yöneticiler varsayılan olarak ve diğer kullanıcılar sudoers dosya, diğer kullanıcıları aracılığıyla kimliğine bürünebilir sudo.
  • Aşağıdaki dayanmaktadır varsayılan yapılandırması sudo - yapılandırmasını değiştirmek, farklı davranmasını sağlayabilir - bkz. man sudoers.

temel biçim komutun başka bir kullanıcı olarak çalıştırılması:

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

Not:

  • Belirtmeyi ihmal ederseniz -H, kimliğe bürünme süreci (belirtilen kullanıcı bağlamında çağrılan işlem) orijinal kullanıcının giriş dizini $HOME. 
  • Kimliğe bürünme işlemi, çağırma işlemi ile aynı çalışma dizinine sahip olacaktır.
  • Kimliğe bürünme işlemi gerçekleştirir kabuk genişletme yok dize değişmezleri argüman olarak geçirilir, çünkü hiçbir kabuk, kimliğe bürünme işlemine katılmazsa ( someExe bir kabuk olur) - genişletmeler çağıran kabuk - kimliğe bürünme işlemine geçmeden önce - açıkça görülebilir.

İsteğe bağlı olarak, kimliğine bürünme işlemine sahip olabilirsiniz. bir (n kimliğine bürünen) kabuk ile veya aracılığıyla çalıştırönekleyerek someExe ya ile -i  veya  -s - belirtilmemiş someExe ... bir oluşturur interaktif kabuk:

  • -i bir oluşturur oturum aç için kabuk someUser, aşağıdakileri ima eder:

    • someUser'ler Kullanıcıya özel kabuk profili tanımlanmışsa yüklenir.
    • $HOME noktalar someUserev dizini, yani ihtiyaç yok -H (yine de belirtebilirsiniz)
    • Kimliğe bürünen kabuk için çalışma dizini someUserev dizini.
  • -s giriş yapılmayan bir kabuk oluşturur:

    • kabuk yok profil yüklendi (etkileşimli dosyalar için başlatma dosyaları olsa da nonlogin kabuklar; Örneğin., ~/.bashrc)
    • Ayrıca belirtmediğiniz sürece -H, kimliğe bürünme süreci orijinal kullanıcının giriş dizini $HOME. 
    • Kimliğe bürünen kabuk, çağırma işlemi ile aynı çalışma dizinine sahip olacaktır.

Bir kabuk kullanmak, komut satırında iletilen dize argümanlarının MAY olabilir kabuk genişletmelere tabi - aşağıdaki platforma özgü farklılıkları görün - taklit edici kabuk tarafından (muhtemelen çığır açan kabuk tarafından ilk genişlemeden sonra); Aşağıdaki iki komutu karşılaştırın ( tek tarafından erken genişlemeyi önlemek için teklifler çağıran kabuk):

  # Run root's shell profile, change to root's home dir.
sudo -u root -i eval 'echo $SHELL - $USER - $HOME - $PWD'
  # Don't run root's 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'

Cehennem nedir çağrılırsa "SHELL ortam değişkeni ayarlanmışsa veya şifre passwd (5) 'de belirtildiği gibi" ile belirlenir. man sudo). İle unutmayın -s o çağıran kullanıcının çevresi önemlidir, oysa -i o taklit kullanıcılar.

Olduğunu unutmayın Kabukla ilgili davranışlarla ilgili platform farklılıkları (ile -i veya -s):

  • sudo Linux'ta görünüşe göre sadece bir yürütülebilir veya yerleşik olarak adlandır ilk aşağıdaki argüman -s/-iOSX, tüm bir kabuk komut satırını geçirmeyi sağlarken; ör. OSX kabul eder sudo -u root -s 'echo $SHELL - $USER - $HOME - $PWD' doğrudan (gerek yok eval), Linux ( sudo 1.8.95p).

  • Eski sürümleri sudo Linux'ta bir kabuktan geçirilen argümanlara kabuk genişletme uygulanmaz; örneğin sudo 1.8.3p1 (ör. Ubuntu 12.04), sudo -u root -H -s echo '$HOME' Kök kullanıcı bağlamında değişken referansı genişletmek yerine sadece "$ HOME" dizesini ekler. En az olarak sudo 1.8.9p5 (ör. Ubuntu 14.04) bu düzeltildi. Bu nedenle, Linux ile daha da genişlemeyi sağlamak için sudo sürümleri, tüm komutu tek bir argüman olarak iletir eval; Örneğin.: sudo -u root -H -s eval 'echo $HOME'. (OSX'de gerekli olmasa da, bu da orada çalışacaktır.)

  • root kullanıcılar $SHELL değişken içerir /bin/sh OSX 10.9'da iken, /bin/bash Ubuntu'da 12.04.

Kimliğe bürünme işleminin bir kabuk içerip içermediğine bakılmaksızın, çevresi aşağıdaki değişkenleri belirleyerek, çağrıcı kullanıcıyı ve komutu yansıtır: SUDO_COMMAND, SUDO_USER, SUDO_UID=, SUDO_GID.

Görmek man sudo ve man sudoers daha birçok incelik için.

@DavidW için şapka ucu ve @ İlham için ilham verin.


73
2017-12-10 22:41





BASH'da bir kullanıcının bulabilirsiniz $HOME Kullanıcının giriş kimliğini bir tilde karakteriyle önekleyerek dizin. Örneğin:

$ echo ~bob

Bu kullanıcı yankılanacak bob'ler $HOME dizin.

Ancak, belirli bir kullanıcı olarak bir komut dosyasını yürütmek istediğinizi söylüyorsunuz. Bunu yapmak için kurulum yapmanız gerekiyor sudo. Bu komut, belirli komutları belirli bir kullanıcı olarak çalıştırmanıza izin verir. Örneğin, yürütmek fookullanıcı olarak bob:

$ sudo -i -ubob -sfoo

Bu yeni bir kabuk başlatır ve -i Kullanıcının varsayılan ortamı ve kabuğu ile bir giriş simüle edecek (yani foo komut bob's$ HOME` dizini.)

Sudo kurulum için biraz karmaşık ve sadece shudders dosyasını görebilmek için bir süper kullanıcı olmanız gerekiyor (genellikle /etc/sudoers). Ancak, bu dosya genellikle kullanabileceğiniz birkaç örneğe sahiptir.

Bu dosyada, bir komutu kimin çalıştırabileceğini belirttiğiniz komutları belirtebilirsiniz. Bu komut, kullanıcının o komutu çalıştırmadan önce parolasını girip girmeyeceğini belirtir. Bu normalde varsayılandır (çünkü kullanıcının bir Kola alırken gelen kullanıcı değil, kullanıcı olduğunu kanıtlar.) Ancak, bir kabuk komut dosyasını çalıştırdığınızda genellikle bu özelliği devre dışı bırakmak istersiniz.


20
2017-12-10 21:29



Umut verici ama -i ve -s karşılıklı olarak özel görünmektedir. Sadece -i yeterli olmalı. - mklement0
Atama sorun ~$different_user bir değişkene $HOME. Bir örnek verebilir misiniz? - Andrew
@Andrew Tırnak işaretleri kullanmayın! user_home=~$different_user. Not etrafında tırnak işaretleri yoktur. ~$different_user. İşletim Sisteminiz ayrıca sizi yeniden atamanızı engelleyebilir HOME çünkü özel bir anlamı var. Kullanıyor musun sudo? Önerilen yol budur. - David W.


Sadece bir kullanıcının evi dir bulmak için hafif bir yol arayanlar için alternatif bir cevap uğruna ...

İle uğraşmak yerine su hack, ya da başka bir fırlatma başlığının ile rahatsız bash sadece bulmak için kabuk $HOME Çevre değişkeni...

Bash ile Hafif Basit Homedir Sorgu

Özellikle bunun için bir komut var: getent

getent passwd someuser | cut -f6 -d:

getent daha fazlasını yapabilirsin ... sadece gör adam sayfası. passwd nsswitch veritabanı kullanıcının girişini döndürür /etc/passwd biçim. Sadece iki nokta üst üste böl : alanları ayrıştırmak için.

Çoğu Linux sisteminde (veya kullanan herhangi bir sistemde) kurulmalıdır. GNU Lib C (RHEL: glibc-common, Deb: libc-bin)


14
2018-01-29 06:29



getent belirttiğiniz gibi Linux'a özgüdür; daha basit ve platform-nötr bir yol bash kullanmaktır tilde genişlemesi ilgi kullanıcı adıylaeval gereklidir, çünkü kullanıcı adı bir belirtilmemiş edebi genişleme çalışması için): eval echo "~$different_user" - her zamanki uyarılar eval uygulamak. - mklement0
Bash yapmak için çok iyi bir fikir! Mevcut kullanıcı ev için başka bir alternatif: eval echo "~$(who -m | awk '{ print $1 }')" ya da sadece eval echo "~". Mac OS X'te, dscl yardımcı program, ama çıktı ayrıştırmak için çok daha zor ve zaten içinde geçiş yapmanızı gerektirir /Users homedir veya uid (ör. dscl . -read /Users/$(who -m | awk '{ print $1 }')  veya dscl . -search /Users UniqueID $(id -u)). Bazı platformlarda sadece bash'ı kullanmak ya da bir şekilde temel işletim sistemi algılaması yapmak daha kolay olabilir. - TrinitronX
Mevcut kullanıcı için ihtiyacınız yok eval hiç: seçilmemiş ~ geçerli kullanıcının ana dizinini döndürür (ör. echo ~). Mevcut kullanıcının kullanıcı adına gerçekten ihtiyacınız varsa, $USER En basit, verimli ve POSIX uyumludur; whoami ayrıca basit, ancak nispeten pahalı ve POSIX olmayan. Sizin who -mtabanlı komut, POSIX uyumlu iken, daha da pahalı. Sonuç olarak: evet, POSIX uyumlu bir kabuk (ör., Bash) kullanmak en basit, en verimli ve taşınabilirdir. - mklement0
getent Linux'a özgüdür, ama neden? Açıkça kullanışlı bir şey var gibi görünüyor (temel olarak bir metin sorgulamak için bir komut satırı arabirimi, bir metin dosyaları aracılığıyla uygulanan olsa da) ve de kolayca taşınabilir olması gerekir. Eh, ek olarak kayıt değerlerini ayıklamak için bir yolu olmalıdır. Bu döner kavşak kullanımı önlemek cut - David Tonhofer
@DavidTonhofer: Bunun nedeni getent sadece okumak yerine /etc/passwd farklı kullanıcı kaynakları ve giriş kimlik doğrulama verileri arka uç potansiyeli nedeniyle. Kullanıcı veritabanı için çeşitli arka planlar vardır. sssd (sss / LDAP), NIS ve NIS +. Bununla ilgili daha fazla bilgi için lütfen bkz. Bu SE nsswitch.conf hakkında cevap. Ekstra kesime duyulan gereksinim, kabul ettiğim en büyük şey değil, ama bu araç çıktıları. Kullanmanın gerçek nedeni getent yapılandırılmış kullanıcı veritabanı arka ucunu sistemde sorgulamaya çalışmaktır. - TrinitronX


Sen istiyorsun -u seçeneği sudo bu durumda. İtibaren man sayfa:

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

Aslında onlar gibi çalıştırmanız gerekmiyorsa, ev dizinine ~<user>. Gibi, benim ev dizinine taşımak için cd ~chooban.


3
2017-12-10 20:57



ihtiyacım var -u hangi komut ile seçeneği? - Andrew
Şunu mu demek istedin: sudo -u $different_user su -? - Andrew
@Andrew Hayır! Yapma su diğer kullanıcı olarak. O kullanıcı olarak çalıştırmak istediğiniz komutu kullanın. Örneğin, sudo -u $different_user $command - David W.
@DavidW Sanırım birden çok komut çalıştırmak için bir yol bulmaya çalışıyordum - Andrew
İle birden çok komut çalıştırabilirsiniz. sudo tek bir komut dosyasında ihtiyacınız varsa buysa. Sudo'nun kullanılması ve kurulumunun yapılması, bununla ilgili en iyi yoldur. Komutlarınız sormadan kullanıcı olarak çalışabilir. Aksi takdirde, bu kullanıcı olarak oturum açmanız ve yeni bir kabuk başlatmanız gerekir, bu da komutlarınızı manuel olarak çalıştırmanız gerektiği anlamına gelir. Bunu otomatik olarak yapmak istiyorsun. - David W.


Yani sen istiyorsun:

  1. gerçekleştirmek bir bash betiğinin parçası farklı bir kullanıcı olarak
  2. o kullanıcının $ HOME dizinine geç

Tarafından ilham bu cevapİşte betiğinizin uyarlanmış hali:

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

Bunu çalıştırdığınızda, aşağıdakileri almalısınız:

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

2
2017-12-10 21:11



Kullanmalısın #!/usr/bin/env bash Shebang olarak. - RedX
@RedX Eğer Linux'ta değilseniz, varsayalım. - Michael Kropat
Görmek stackoverflow.com/questions/10376206/preferred-bash-shebang - RedX


Bu Linux'ta çalışıyor. Diğer * nixes'de nasıl davrandığından emin değil.

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

2
2017-08-19 16:59





Ben de bunun peşindeydim, ama bir kullanıcıyı sadece bir yol elde etmek için taklit etmek istemiyordum!

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

Şimdi senaryonuzda, $user_path çoğu durumda /home/username

Varsayalım: Daha önce belirlediniz $username amaçlanan kullanıcı kullanıcı değeri ile. Kaynak: http://www.unix.com/shell-programming-and-scripting/171782-cut-fields-etc-passwd-file-into-variables.html


0
2017-12-28 23:18



Şifre dosyası sadece yerel kullanıcıları içerir, bu yüzden AD / LDAP entegre kullanıcıları için çalışmaz. Bunun yerine 'getent' tarafından sağlanan soyutlama katmanını kullanmalısınız (yukarıdaki örneğe bakınız) - Saustrup
Oh harika! TIL. :-) Şimdi bu senaryoyu bulmalıyım. - Grizly