Bu kullanıcı olarak bash betiğinin geri kalanını yürütmek için su'yu nasıl kullanabilirim?


126

Argüman olarak, bir kullanıcı adı ve bir projenin birleşimi olan bir dizeyi alan bir betik yazdım. Betiğin (su) kullanıcı adına, cd proje dizesine bağlı olarak belirli bir dizine geçmesi beklenir.

Temelde yapmak istiyorum:

su $USERNAME;  
cd /home/$USERNAME/$PROJECT;  
svn update;  

Sorun şu ki, bir kez bir su ... yaparsam orada bekler. Bu, yürütme akışı kullanıcıya geçişe geçtiğinden beri mantıklı. Çıktıktan sonra, geri kalan şeyler yürütülür ancak istenildiği gibi çalışmaz.

Svn komutunun başına su ekledim ancak komut başarısız oldu (yani istenen dizindeki svn'yi güncellemedi).

Kullanıcının kullanıcıyı değiştirmesine ve svn'yi (diğer şeylerin yanı sıra) çağırmasına olanak tanıyan bir komut dosyasını nasıl yazabilirim?

Yanıtlar:


86

İşin püf noktası "su" yerine "sudo" komutunu kullanmaktır.

Bunu eklemeniz gerekebilir

username1 ALL=(username2) NOPASSWD: /path/to/svn

/ etc / sudoers dosyanıza

ve komut dosyanızı şu şekilde değiştirin:

sudo -u username2 -H sh -c "cd /home/$USERNAME/$PROJECT; svn update" 

Username2, SVN komutunu çalıştırmak istediğiniz kullanıcı ve username1 komut dosyasını çalıştıran kullanıcıdır.

Bu komut dosyasını çalıştırmak için birden fazla kullanıcıya ihtiyacınız varsa %groupname, username1 yerine a kullanın.


Benzer bir sorunum var ama chshdiğer kullanıcılar için koşmak istedim . Sorunum burada stackoverflow.com/q/15307289/80353 adresinde listelenmiştir Cevabınızı durumuma nasıl uyarlayabilirim?
Kim Stacks

Bunu yaptım - ama yine de bir şifre sordu.
Hippyjim

@Hippyjim Kullanıcı adlarını doğru aldığınızdan emin misiniz?
Kimvais

1
Yaptım - aynı zamanda / bin / bash kullanımına da izin vermem gerektiği ortaya çıktı.
Hippyjim

3
Kullanmanız sudoya suda ikincil öneme sahip olmanız , sudoçok daha güvenli ve kullanışlıdır.
üçlü

105

Çok daha basit: sudobir kabuğu çalıştırmak için kullanın ve komutları beslemek için bir yorumlu dosya kullanın.

#!/usr/bin/env bash
whoami
sudo -i -u someuser bash << EOF
echo "In"
whoami
EOF
echo "Out"
whoami

( orijinal olarak SuperUser'da cevap )


5
Bu cevap en iyi sonucu verdi. Beklenen ortamı -ielde etmek için seçeneği kullanmanızı öneririm someuser.
not2savvy

2
sudokullanışlı olabilir, ancak kutunun dışında değilse iyi değildir (AIX'teki gibi). su -c 'commands'doğru cevaptır.
Zor

1
Destansı çözüm!
3bdalla

Herdoc kapsamında değişkenler nasıl kullanılabilir hale getirilir?
dotslashlu

AIX'te bu hatayı atar ksh: sh: 0403-006 Yürütme izni reddedildi.
AhmedRana

54

Komut dosyasının geri kalan kısmını veya bir kısmını başka bir kullanıcı altında yürütmek için aşağıdaki gibi bir komut dosyası kullanın:

#!/bin/sh

id

exec sudo -u transmission /bin/sh - << eof

id

eof

11
$ HOME gibi şeylerin doğru ayarlandığından emin olmak için "sudo -i -u ..." kullanmak isteyebilirsiniz.
Bryan Larsen

Çaylak soru için üzgünüm, ama burada bir kimlik nedir?
Nitin Jadhav

1
@NitinJadhav, burada sadece mevcut kullanıcının kimliğini göstermek için kullandı, kökün kimliği 0, bu nedenle ilk kimlik size bir sayı gösterecek, ancak ikincisi kesinlikle 0 gösterecek (çünkü ikincisi içeride çalıştırıldı root tarafından çalıştırılan bir blok). Bunun whoamiyerine idkimliği yerine ad döndürecek bir kullanıcı yapabilirsiniz
Mohammed Noureldin

@MohammedNoureldin Teşekkürler!
Nitin Jadhav

sudokullanışlı olabilir, ancak kutunun dışında değilse iyi değildir (AIX'teki gibi). su -c 'commands'doğru cevaptır.
Zor

52

Tüm farklı kullanıcı komutlarını kendi komut dosyası olarak yürütmeniz gerekir. Yalnızca bir veya birkaç komutsa, satır içi çalışmalıdır. Çok sayıda komut içeriyorsa, muhtemelen bunları kendi dosyalarına taşımak en iyisidir.

su -c "cd /home/$USERNAME/$PROJECT ; svn update" -m "$USERNAME" 

4
Bu tek doğru cevap. Sudo bunun için gerekli değildir.
helvete

1
Kabuk sağlamanız da gerekebilir su -s /bin/bash.
mixel

kök kullanıcılar için en iyi çözüm
rfinz

Varsayılan olarak sudo yüklemeyenler için en iyi cevap (Sana bakıyorum AIX)
Zor

46

İşte benim durumumda daha uygun olan başka bir yaklaşım (sadece kök ayrıcalıklarını bırakmak ve komut dosyamın geri kalanını kısıtlı kullanıcıdan yapmak istedim): betiğin kendisini doğru kullanıcıdan yeniden başlatmasını sağlayabilirsiniz. Başlangıçta root olarak çalıştırıldığını varsayalım. O zaman şöyle görünecek:

#!/bin/bash
if [ $UID -eq 0 ]; then
  user=$1
  dir=$2
  shift 2     # if you need some other parameters
  cd "$dir"
  exec su "$user" "$0" -- "$@"
  # nothing will be executed beyond that line,
  # because exec replaces running process with the new one
fi

echo "This will be run from user $UID"
...

6
Bunun neden daha yüksek puanlı olmadığını merak ediyorum. Her şeyi bash içinde tutarken orijinal soruyu en iyi şekilde çözmektir.
SirVer

Veya runuser -u $user -- "$@"su (1)
cghislai'de

1
exec su "$user" "$0" -- "$@"
macieksk

1
Teşekkürler @macieksk, iyi yakaladım. Güncellenecek. --Gerçekten yararlıdır.
MarSoft

1
Sunulan yaklaşım en iyisidir ve eksiksizdir. Hepsi tek bir komut dosyası içinde yazılır ve tümü bash kullanır. Etkili olarak, bu komut dosyası iki kez çalıştırılır. İlk betik testinde bu köktür, sonra ortamı hazırlar ve su ile kullanıcıyı değiştirir. Ama bunu exec komutuyla yapın, o zaman sadece tek bir betik örneği vardır. İkinci döngüde, if / fi ifadesi çıkarılır, ardından komut dosyası doğrudan hazırlanmış eylemi gerçekleştirir. Bu örnekte yankıdır. Diğer tüm yaklaşımlar sorunu yalnızca kısmen çözer. Elbette bu komut dosyası sh değil bash altında çalıştırılabilir, ancak $ HOME özel değişkenini test etmeliyiz, $ UID değil
Znik

7

sudoBunun yerine kullanın

DÜZENLEME : Douglas'ın da belirttiği gibi, harici bir komut olmadığı için cdin kullanamazsınız . İşi yapmak için komutları bir alt kabukta çalıştırmanız gerekir .sudocd

sudo -u $USERNAME -H sh -c "cd ~/$PROJECT; svn update"

sudo -u $USERNAME -H cd ~/$PROJECT
sudo -u $USERNAME svn update

Bu kullanıcının şifresini girmeniz istenebilir, ancak yalnızca bir kez.


Yine de bu işe yaramayacak - cd, ilk sudo'nun yürütülmesi bittikten sonra kaybolacak.
Douglas Leeder 01

Aslında, cd'yi doğrudan çağıramazsınız çünkü bu harici bir komut değildir .
iamamac

sudokullanışlı olabilir, ancak kutunun dışında değilse iyi değildir (AIX'teki gibi). su -c 'commands'doğru cevaptır.
Zor

6

Kullanıcıyı bir kabuk betiği içinde değiştirmek mümkün değildir. Diğer yanıtlarda açıklanan sudo'yu kullanan geçici çözümler muhtemelen en iyi seçeneğinizdir.

Perl betiklerini root olarak çalıştıracak kadar deliyseniz, bunu $< $( $> $) real / effective uid / gid tutan değişkenlerle yapabilirsiniz , örneğin:

#!/usr/bin/perl -w
$user = shift;
if (!$<) {
    $> = getpwnam $user;
    $) = getgrnam $user;
} else {
    die 'must be root to change uid';
}
system('whoami');

Sanki -1 IS mümkün sudo ile geçici olarak başka bir kullanıcının haklarını kazanmak için.
Kimvais

4
Kabuk betiğinin kullanıcının değiştirilemeyecek şekilde çalışması anlamında mümkün değildir (asıl soru sorulan budur). Sudo ile diğer işlemleri çağırmak, komut dosyasının kendisinin çalıştırdığı kişiyi değiştirmez.
P-Nuts

2

Bu benim için çalıştı

"Temel hazırlığımı" "başlangıçtan" ​​ayırıyorum.

 # Configure everything else ready to run 
  config.vm.provision :shell, path: "provision.sh"
  config.vm.provision :shell, path: "start_env.sh", run: "always"

sonra start_env.sh dosyamda

#!/usr/bin/env bash

echo "Starting Server Env"
#java -jar /usr/lib/node_modules/selenium-server-standalone-jar/jar/selenium-server-standalone-2.40.0.jar  &
#(cd /vagrant_projects/myproj && sudo -u vagrant -H sh -c "nohup npm install 0<&- &>/dev/null &;bower install 0<&- &>/dev/null &")
cd /vagrant_projects/myproj
nohup grunt connect:server:keepalive 0<&- &>/dev/null &
nohup apimocker -c /vagrant_projects/myproj/mock_api_data/config.json 0<&- &>/dev/null &

-2

@ MarSoft'un fikrinden ilham aldım ama satırları şu şekilde değiştirdim:

USERNAME='desireduser'
COMMAND=$0
COMMANDARGS="$(printf " %q" "${@}")"
if [ $(whoami) != "$USERNAME" ]; then
  exec sudo -E su $USERNAME -c "/usr/bin/bash -l $COMMAND $COMMANDARGS"
  exit
fi

sudoKomut dosyasının şifresiz yürütülmesine izin vermek için kullandım . Kullanıcı için bir şifre girmek istiyorsanız sudo,. Ortam değişkenlerine ihtiyacınız yoksa -Esudo'dan kaldırın .

/usr/bin/bash -lOlmasını sağlar, bu profile.dkomut bir başlatılmış çevre için yürütülür.


sudokullanışlı olabilir, ancak kutunun dışında değilse iyi değildir (AIX'teki gibi). su -c 'commands'doğru cevaptır.
Zor

@Tricky Belki de tam cevabı okuyun, zaten kaldırmayı öneriyor sudo. Aslında, sudo o kadar basit değil, birçok durumda sudo -Etty olmadan çalıştırmaya izin vermek için sudoers.d'de bir bile ve bir yapılandırma girişine ihtiyacınız var !requiretty. Ancak, bir şifre iletişim kutusunun müdahale edebileceği otomatik olarak adlandırılan komut dosyaları için sudo'nun gerekli olduğu birçok durum vardır. Bu yüzden onu standart bir çözümden çıkarmam.
Trendfischer

Söz konusu kod düpedüz hatalı - komut dosyası adlarını veya boşluklu argümanları kırar; "$@"Bir dizenin içine koymanın , ilkini geçen argümanların bağımsız bir dizeye ekleneceği , argümana dahil edilmediği anlamına geldiğini unutmayın -c. Güvenli hale getirmek istiyorsan, printf -v arg_q '%q ' "$0" "$@"kullanabilir ve sonra kullanabilirsinsu "$USERNAME" -c "/usr/bin/bash -l $arg_q"
Charles Duffy

@CharlesDuffy Haklısın! Bu cevap için üretim senaryomu çok fazla basitleştirdim :-( Sadece bir ekleme COMMANDARGS=$@sorunu çözer -c. Boşluklu argümanlar daha önce sorun değildi, ancak iyi girdinizi uyguladım. Çalışması için bazı deneyler yapmam gerekiyordu. I soruyu düzenledim ve umarım başka bir hata yapıştırmadım.
Yorumunuz
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.