แนวปฏิบัติที่เหมาะสมที่สุดในการเรียกใช้บริการ Linux ในฐานะผู้ใช้อื่น


141

บริการเริ่มต้นที่จะเริ่มต้นrootณ เวลาบูตในกล่อง RHEL ของฉัน ถ้าผมจำได้อย่างถูกต้องเดียวกันเป็นจริงสำหรับลินุกซ์ distros อื่น ๆ ที่ใช้สคริปต์ init /etc/init.dใน

คุณคิดว่าอะไรคือวิธีที่ดีที่สุดที่จะให้กระบวนการทำงานแทนในฐานะผู้ใช้ (แบบคงที่) ที่ฉันเลือก

วิธีเดียวที่ฉันไปถึงคือใช้สิ่งที่ชอบ:

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

แต่ดูเหมือนจะไม่เป็นระเบียบ ...

มีเวทย์มนตร์บ้างไหมที่ให้กลไกง่าย ๆ ในการเริ่มให้บริการโดยอัตโนมัติเหมือนกับผู้ใช้ที่ไม่ใช่ผู้ใช้รูทอื่น ๆ ?

แก้ไข:ฉันควรได้กล่าวว่ากระบวนการที่ฉันเริ่มต้นในกรณีนี้เป็นสคริปต์ Python หรือโปรแกรม Java ฉันไม่ควรเขียน wrapper พื้นเมืองรอบตัวพวกเขาดังนั้นฉันจึงไม่สามารถเรียกsetuid ()ตามที่Blackแนะนำ


Python ไม่ได้ให้การเข้าถึงการเรียกของระบบ setuid () หรือไม่? ดูเหมือนว่าจะเป็นข้อบกพร่องที่ร้ายแรงเมื่อเทียบกับ Perl
Jonathan Leffler

12
ว้าวใช่แล้ว: os.setuid (uid) ทุกวันเป็นวันเรียน!
James Brady

คำตอบ:


67

บนเดเบียนเราใช้ start-stop-daemonยูทิลิตี้นี้ซึ่งจัดการไฟล์ pid เปลี่ยนผู้ใช้ทำให้ daemon อยู่ในพื้นหลังและอีกมากมาย

ฉันไม่คุ้นเคยกับ RedHat แต่daemonยูทิลิตี้ที่คุณใช้อยู่แล้ว (ซึ่งถูกกำหนดใน/etc/init.d/functions, btw.) ถูกกล่าวถึงทุกที่เทียบเท่ากับstart-stop-daemonดังนั้นมันสามารถเปลี่ยน uid ของโปรแกรมของคุณหรือวิธีที่คุณทำ มันถูกต้องแล้ว

หากคุณมองไปรอบ ๆ อินเทอร์เน็ตมีหลายห่อที่คุณสามารถใช้ได้ บางคนอาจได้รับการบรรจุใน RedHat แล้ว ลองดูdaemonizeตัวอย่าง


การอ้างอิง x น่าสนใจ ฉันมีโปรแกรม daemonize ของตัวเองคล้ายกันมาก ไม่ได้ทำ pidfile หรือ lockfile ตั้ง umask ฉันมีโปรแกรมรูท SUID แยกต่างหากสำหรับการตั้งค่า UID, GID, EUID, EGID และ aux (เรียกว่า asroot) ฉันใช้ 'asroot [opts] - env ​​-i [env] daemonize [opts] - คำสั่ง [opts]'
Jonathan Leffler

(ต่อ): โปรแกรม env POSIX มาตรฐานไม่ยอมรับ '-' ระหว่างการตั้งค่าสภาพแวดล้อมและคำสั่งที่ดำเนินการ (irksome แต่เป็นเช่นนั้น)
Jonathan Leffler

4
daemon สามารถใช้ฟังก์ชันจาก /etc/init.d/functions ในสคริปต์ upstart ได้อย่างไร? คุณช่วยแสดงตัวอย่างได้ไหม
Meglio

10
ใน Debian /etc/init.d/skeletonเห็น เพิ่มตัวแปร UID, GID และการdo_start()ใช้งาน:start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --chuid $UID:$GID -- $DAEMON_ARGS
Jonathan Ben-Avraham

ฉันสังเกตเห็นว่าdaemon()มีการกำหนดไว้ใน/etc/rc.d/init.d/functionทั้งกล่อง RHEL และ CentOS ของฉัน
quickshiftin

53

หลังจากดูคำแนะนำทั้งหมดที่นี่ฉันได้ค้นพบบางสิ่งที่ฉันหวังว่าจะเป็นประโยชน์กับคนอื่นในตำแหน่งของฉัน:

  1. hopมีสิทธิ์ชี้ให้ฉันย้อนกลับไปที่/etc/init.d/functions: daemonฟังก์ชั่นอนุญาตให้คุณตั้งค่าผู้ใช้อื่น:

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

    สิ่งนี้ถูกนำไปใช้โดยการปิดกระบวนการเรียกใช้ด้วยrunuser- เพิ่มเติมในภายหลัง

  2. Jonathan Lefflerถูกต้อง: มี setuid ใน Python:

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

    ฉันยังคงไม่คิดว่าคุณสามารถกำหนดได้จากภายใน JVM อย่างไรก็ตาม

  3. ทั้งsuมิได้runuser รับมือกรณีที่คุณขอใช้คำสั่งเป็นผู้ใช้ที่คุณมีอยู่แล้วเป็น เช่น:

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

เพื่อแก้ไขปัญหาพฤติกรรมดังกล่าวของsuและrunuserฉันได้เปลี่ยนสคริปต์เริ่มต้นของฉันเป็นดังนี้:

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

ขอบคุณสำหรับความช่วยเหลือของคุณ!


5
  • daemons บางตัว (เช่น apache) ทำสิ่งนี้ด้วยตนเองโดยเรียกsetuid ()
  • คุณสามารถใช้การตั้งค่าสถานะไฟล์ setuidเพื่อเรียกใช้กระบวนการเป็นผู้ใช้ที่แตกต่างกัน
  • แน่นอนว่าโซลูชันที่คุณกล่าวถึงทำงานได้ดีเช่นกัน

หากคุณตั้งใจจะเขียนภูตของคุณเองฉันแนะนำให้โทรไปที่ setuid () ด้วยวิธีนี้กระบวนการของคุณสามารถ

  1. ใช้ประโยชน์จากสิทธิ์รูท (เช่นเปิดไฟล์บันทึกสร้างไฟล์ pid)
  2. ดร็อปสิทธิพิเศษรูทที่จุดใดจุดหนึ่งระหว่างการเริ่มต้น

3

เพียงเพิ่มสิ่งอื่น ๆ ที่ต้องระวัง:

  • Sudo ในสคริปต์ init.d ไม่ดีเนื่องจากต้องใช้ tty ("sudo: ขออภัยคุณต้องมี tty ในการเรียกใช้ sudo")
  • หากคุณกำลัง daemonizing แอ็พพลิเคชัน java คุณอาจต้องการพิจารณา Java Service Wrapper (ซึ่งจัดเตรียมกลไกสำหรับการตั้งค่า id ผู้ใช้)
  • ทางเลือกอื่นอาจเป็นsu --session-command = [cmd] [ผู้ใช้]

3

บนเครื่องเสมือน CENTOS (Red Hat) สำหรับเซิร์ฟเวอร์ svn: แก้ไข/etc/init.d/svnserver เพื่อเปลี่ยน pid เป็นสิ่งที่ svn สามารถเขียนได้:

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

และตัวเลือกเพิ่มเติม--user=svn:

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

pidfile /var/run/svnserve.pidเดิม daemon ไม่ได้เริ่มเพราะรากเท่านั้นที่สามารถเขียนได้

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

3
สิ่งนี้สร้างช่องโหว่การเพิ่มระดับสิทธิ์ ผู้ใช้ svn สามารถใส่ PID เองได้ในไฟล์ /home/svn/run/svnserve.pid ซึ่งจะถูกฆ่าแทนกระบวนการ svn เมื่อใดก็ตามที่บริการ svn หยุดทำงานหรือรีสตาร์ท
rbu

2

สิ่งที่ต้องระวัง:

  • ดังที่คุณกล่าวไว้ su จะถามรหัสผ่านหากคุณเป็นผู้ใช้เป้าหมายแล้ว
  • ในทำนองเดียวกัน setuid (2) จะล้มเหลวหากคุณเป็นผู้ใช้เป้าหมาย (ในระบบปฏิบัติการบางระบบ)
  • setuid (2) ไม่ได้ติดตั้งสิทธิพิเศษหรือการควบคุมทรัพยากรที่กำหนดไว้ใน /etc/limits.conf (Linux) หรือ / etc / user_attr (Solaris)
  • หากคุณไปเส้นทาง setgid (2) / setuid (2) อย่าลืมเรียกกลุ่มเริ่มต้น (3) - เพิ่มเติม ที่นี่

โดยทั่วไปฉันใช้ / sbin / su เพื่อสลับไปใช้ผู้ใช้ที่เหมาะสมก่อนที่จะเริ่ม daemons


2

ทำไมไม่ลองต่อไปนี้ในสคริปต์เริ่มต้น:

setuid $USER application_name

มันใช้งานได้สำหรับฉัน


3
สิ่งนี้ไม่สามารถใช้ได้ในทุก distros ฉันลองใช้ RHEL 7:setuid: command not found
Cocowalla

0

ฉันต้องการเรียกใช้แอปพลิเคชัน Spring .jar เป็นบริการและพบวิธีที่ง่ายในการเรียกใช้ในฐานะผู้ใช้เฉพาะ:

ฉันเปลี่ยนเจ้าของและกลุ่มไฟล์ jar ของฉันเป็นผู้ใช้ที่ฉันต้องการเรียกใช้ จากนั้น symlinked jar นี้ใน init.d และเริ่มบริการ

ดังนั้น:

#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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.