Linux hizmetini farklı bir kullanıcı olarak çalıştırmak için en iyi uygulama


141

Hizmetler varsayılan olarak root, RHEL kutumdaki önyükleme sırasında olduğu gibi başlar . Doğru hatırlıyorsam, init komut dosyalarını kullanan diğer Linux dağıtımları için de aynı şey geçerlidir /etc/init.d.

İşlemleri benim seçtiğim (statik) bir kullanıcı olarak çalıştırmanın en iyi yolu nedir?

Geldiğim tek yöntem şöyle bir şey kullanmaktı:

 su my_user -c 'daemon my_cmd &>/dev/null &'

Ama bu biraz düzensiz görünüyor ...

Kök olmayan kullanıcılar gibi hizmetleri otomatik olarak başlatmak için kolay bir mekanizma sağlayan biraz sihir sıkışmış mı?

EDIT: Bu örnekte başlattığım işlemlerin Python komut dosyaları veya Java programları olduğunu söylemeliydim. Etraflarına yerel bir paket yazmak istemem, bu yüzden maalesef Black'in önerdiği gibi setuid () yöntemini çağıramıyorum .


Python, setuid () sistem çağrıları ailesine erişim sağlamıyor mu? Bu, Perl'e kıyasla ciddi bir kusur gibi görünüyor.
Jonathan Leffler

12
Vay canına, evet öyle: os.setuid (uid). Her gün bir okul günü!
James Brady

Yanıtlar:


67

Debian'da start-stop-daemonpid dosyalarını işleyen, kullanıcıyı değiştiren, arka plan programını arka plana koyan ve çok daha fazlasını yapan yardımcı programı kullanıyoruz .

RedHat'a aşina değilim, ancak daemonzaten kullandığınız yardımcı program (ki /etc/init.d/functionsbtw olarak tanımlanır ) her yerde eşdeğer olarak belirtilir start-stop-daemon, bu yüzden ya programınızın uid'ini veya yaptığınız yolu değiştirebilir zaten doğru olanı.

Ağın etrafına bakarsanız, kullanabileceğiniz birkaç hazır ambalaj vardır. Bazıları zaten RedHat'ta paketlenmiş olabilir. daemonizeÖrneğin bir göz atın .


X-ref ilginç. Çok benzer bir programım var; pidfile veya lockfile yapmaz, umask ayarlar. Ben UID, GID, EUID, EGID ve aux grupları (asroot denir) ayarlamak için ayrı bir SUID kök programı var. 'Asroot [opts] - env ​​-i [env] daemonize [opts] - command [opts]' kullanıyorum
Jonathan Leffler

(devam): POSIX standart env programı, ortam ayarı ile yürütülen komut (irksome vb.) arasında '-' kabul etmez.
Jonathan Leffler

4
/Etc/init.d/functions işlevinden daemon işlevi sonradan çalıştırma komut dosyasında nasıl kullanılabilir? Bir örnek gösterebilir misiniz, lütfen.
Meglio

10
Debian'da bkz /etc/init.d/skeleton. UID, GID değişkenleri ekleyin ve do_start()kullanımda:start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --chuid $UID:$GID -- $DAEMON_ARGS
Jonathan Ben-Avraham

Hem RHEL hem de CentOS kutularımda daemon()tanımlandığımı fark ettim /etc/rc.d/init.d/function.
quickshiftin

53

Buradaki tüm önerilere baktıktan sonra, konumumdaki başkaları için yararlı olacağını umduğum birkaç şey keşfettim:

  1. hop beni tekrar işaret etmekte haklıdır /etc/init.d/functions: daemonişlev zaten alternatif bir kullanıcı ayarlamanızı sağlar:

    daemon --user=my_user my_cmd &>/dev/null &
    

    Bu, süreç çağrışımı ile kaydırılarak uygulanır runuser- daha sonra bu konuda daha fazla bilgi.

  2. Jonathan Leffler haklı: Python'da setuid var:

    import os
    os.setuid(501) # UID of my_user is 501
    

    Yine de bir JVM içinden ayarlayabileceğinizi düşünmüyorum.

  3. Halihazırda bulunduğunuz kullanıcı olarak bir komut çalıştırmayı talep ettiğiniz durumu sune runuserzarifçe ne de ele alın. Örneğin:

    [my_user@my_host]$ id
    uid=500(my_user) gid=500(my_user) groups=500(my_user)
    [my_user@my_host]$ su my_user -c "id"
    Password: # don't want to be prompted!
    uid=500(my_user) gid=500(my_user) groups=500(my_user)
    

O davranışı Geçici çözüm için suve runuserben gibi bir şey benim init komut değiştirdik:

if [[ "$USER" == "my_user" ]]
then
    daemon my_cmd &>/dev/null &
else
    daemon --user=my_user my_cmd &>/dev/null &
fi

Yardımlarınız için hepinize teşekkürler!


5
  • Bazı cinler (örn. Apache) bunu setuid () yöntemini çağırarak kendileri yaparlar.
  • İşlemi farklı bir kullanıcı olarak çalıştırmak için setuid-file bayrağını kullanabilirsiniz.
  • Tabii ki, bahsettiğiniz çözüm de işe yarıyor.

Kendi daemon'unuzu yazmak istiyorsanız, setuid () öğesini çağırmanızı öneririm. Bu şekilde, işleminiz

  1. Kök ayrıcalıklarından yararlanın (örn. Açık günlük dosyaları, pid dosyaları oluşturma).
  2. Başlatma sırasında kök ayrıcalıklarını belirli bir noktada bırakın.

3

Dikkat etmeniz gereken başka şeyler eklemek için:

  • Bir init.d betiğinde Sudo iyi değil çünkü tty'ye ihtiyaç duyuyor ("sudo: üzgünüm, sudo çalıştırmak için bir tty'ye sahip olmalısınız")
  • Bir java uygulamasını planlıyorsanız, Java Service Wrapper'ı (kullanıcı kimliğini ayarlamak için bir mekanizma sağlar) dikkate almak isteyebilirsiniz.
  • Başka bir alternatif su --session-command = [cmd] [kullanıcı] olabilir

3

svn sunucusu için bir CENTOS (Red Hat) sanal makinede: pid'i svn'nin yazabileceği bir şeyle /etc/init.d/svnserver değiştirmek için düzenlenmiştir :

pidfile=${PIDFILE-/home/svn/run/svnserve.pid}

ve seçenek eklendi --user=svn:

daemon --pidfile=${pidfile} --user=svn $exec $args

Orijinal pidfile oldu /var/run/svnserve.pid. Daemon başlamadı çünkü sadece kök orada yazabilirdi.

 These all work:
/etc/init.d/svnserve start
/etc/init.d/svnserve stop
/etc/init.d/svnserve restart

3
Bu bir ayrıcalık yükselmesi güvenlik açığı oluşturur. Svn kullanıcısı, svn hizmeti her durdurulduğunda veya yeniden başlatıldığında svn işlemi yerine öldürülecek olan /home/svn/run/svnserve.pid dosyasına rasgele PID'ler yerleştirebilir.
rbu

2

Dikkat edilmesi gereken bazı şeyler:

  • Bahsettiğiniz gibi, su zaten hedef kullanıcıysanız bir parola isteyecektir
  • Benzer şekilde, zaten hedef kullanıcıysanız setuid (2) başarısız olur (bazı işletim sistemlerinde)
  • setuid (2), /etc/limits.conf (Linux) veya / etc / user_attr (Solaris) içinde tanımlanan ayrıcalıkları veya kaynak denetimlerini yüklemez
  • Daha bu konuda - sen setuid setgid (2) / giderseniz (2) rota, initgroups çağırmak için (3) unutma burada

Genel olarak / sbin / su kullanarak cinleri başlatmadan önce uygun kullanıcıya geçiyorum.


2

Neden init betiğinde aşağıdakileri denemiyorsunuz:

setuid $USER application_name

Benim için çalıştı.


3
Bu, tüm dağıtımlarda mevcut değildir. RHEL 7'yi denedim:setuid: command not found
Cocowalla

0

Bir hizmet olarak bir Spring .jar uygulamasını çalıştırmak için gerekli ve belirli bir kullanıcı olarak bu çalıştırmak için basit bir yol buldum:

Jar dosyamın sahibini ve grubunu çalıştırmak istediğim kullanıcıya değiştirdim. Daha sonra init.d içinde bu kavanozu işaretledi ve hizmeti başlattı.

Yani:

#chown myuser:myuser /var/lib/jenkins/workspace/springApp/target/springApp-1.0.jar

#ln -s /var/lib/jenkins/workspace/springApp/target/springApp-1.0.jar /etc/init.d/springApp

#service springApp start

#ps aux | grep java
myuser    9970  5.0  9.9 4071348 386132 ?      Sl   09:38   0:21 /bin/java -Dsun.misc.URLClassPath.disableJarChecking=true -jar /var/lib/jenkins/workspace/springApp/target/springApp-1.0.jar
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.