Mulai skrip sebagai pengguna lain

12

Saya telah membuat skrip di /etc/init.d/ yang harus menjalankan beberapa skrip lain dari pengguna lain (non-root privilege) dari direktori home mereka, seolah-olah mereka memulainya.

Saya meluncurkan skrip ini dengan: sudo -b -u <username> <script_of_a_particular_user>

Dan itu berhasil. Tetapi untuk setiap skrip pengguna yang terus berjalan (misalnya beberapa pengawas) saya melihat proses sudo induk yang sesuai, masih hidup dan berjalan sebagai root. Ini membuat kekacauan dalam daftar proses aktif.

Jadi pertanyaan saya adalah: Bagaimana saya bisa meluncurkan (bercabang) skrip lain dari skrip bash yang ada sebagai pengguna lain dan membiarkannya sebagai proses yatim (berdiri sendiri)?

Penjelasan lebih rinci:
Saya pada dasarnya mencoba memberikan kepada pengguna lain alat untuk menjalankan hal-hal pada saat sistem mulai atau sistem mati dengan menjalankan file yang dapat dieksekusi yang ditemukan di masing-masing subdirektori yang ditemukan di direktori home mereka, bernama .startUp dan .shutDown. Karena saya tidak menemukan cara lain untuk melakukan itu, saya menulis skrip bash saya yang melakukan hal itu dan saya telah mengkonfigurasinya sebagai skrip layanan (dengan mengikuti contoh kerangka) di /etc/init.d/ sehingga ketika dijalankan dengan argumen mulai, ia meluncurkan semuanya dari direktori .startUp dan ketika dijalankan dengan argumen berhenti, ia meluncurkan semuanya dari direktori .shutDown semua pengguna sebagai mereka.

Atau saya juga tertarik jika saya bisa menggunakan beberapa solusi yang ada untuk menyelesaikan masalah ini.

UPDATE
Saya telah melihat-lihat sedikit dan saya menemukan pertanyaan ini: /unix/22478/detach-a-daemon-using-sudo

Jawaban yang diterima di sana, untuk digunakan sudo -u user sh -c "daemon & disown %1":, berfungsi untuk saya. Tetapi saya juga mencoba tanpa menolak% 1 dan itu sama. Jadi inilah yang bekerja untuk saya seperti yang saya harapkan:

sudo -u <username> bash -c "<script_of_a_particular_user> &"

Pertanyaan tambahan saya sekarang adalah, mengapa itu bekerja tanpa disangkal? haruskah saya tetap meninggalkan telepon yang ditolak , untuk beberapa kasus khusus yang potensial?

PEMBARUAN 2

Tampaknya ini juga berfungsi:

su <username> -c "<script_of_a_particular_user> &"

Apakah ada perbedaan antara panggilan ini dan panggilan sudo? Saya tahu ini berpotensi pertanyaan yang berbeda. Tetapi karena saya sendiri yang menemukan jawabannya di sini, mungkin demi topik ini seseorang dapat mengklarifikasi hal ini di sini.

UPDATE 3
Kedua metode ini dengan su atau sudo sekarang menghasilkan proses startpar baru (proses tunggal yang berjalan sebagai root) setelah saya mem-boot mesin. Terlihat dalam daftar proses sebagai:

startpar -f -- <name_of_my_init.d_script>

Mengapa proses ini muncul? Jelas saya melakukan sesuatu yang salah karena tidak ada skrip init.d lain yang menjalankan proses ini.

UPDATE 4
Masalah dengan startpar teratasi. Saya telah memulai pertanyaan lain untuk itu:
proses startpar dibiarkan menggantung ketika memulai proses dari rc.local atau init.d

Dan pertanyaan lain untuk membahas lebih lanjut mekanisme peluncuran untuk pengguna yang tidak memiliki hak istimewa:
Memberikan pengguna normal (non-root) kemampuan inisialisasi dan shutdown yang dijalankan secara otomatis

Ivan Kovacevic
sumber

Jawaban:

18

Jawaban yang benar untuk ini adalah bahwa untuk "daemonisasi" yang tepat, input standar, output standar dan kesalahan standar perlu diarahkan ke / dev / null (atau beberapa file nyata):

su someuser -c "nohup some_script.sh >/dev/null 2>&1 &"

su - gantikan identitas pengguna ke argumenuser -
c - su untuk menjalankan perintah yang ditentukan
nohup - Jalankan perintah yang kebal terhadap hangup. Untuk mencegah kasus di mana proses orang tua akan menghentikan proses anak. Ditambahkan di sini untuk jaga-jaga. Tetapi sebenarnya tidak berpengaruh pada kasus khusus saya. Apakah diperlukan tergantung pada lingkungan (periksa shopt )
> / dev / null - Redirect output standar ke nothing, pada dasarnya menonaktifkannya.
2> & 1 - Redirect standard error (2) output ke output standar (1), yang dialihkan ke null
& - lepas ke latar belakang, ini akan mengarahkan input standar juga ke / dev / null.

Ini pada dasarnya persis seperti apa utilitas start-stop-daemon dari Debian dpkg tidak pada intinya. Itulah sebabnya saya lebih suka memulai skrip dengan cara ini daripada memperkenalkan panggilan utilitas eksternal lain dalam kode saya. start-stop-daemon berguna dalam kasus di mana Anda memiliki program daemon blown penuh yang perlu Anda mulai dan di mana Anda kemudian membutuhkan fungsionalitas tambahan yang disediakan oleh start-stop-daemon (misalnya memeriksa apakah proses yang ditentukan sudah berjalan sehingga tidak dapat meluncurkannya lagi).

Perlu juga dicatat bahwa Anda juga dapat menutup deskriptor file dari proses Anda alih-alih mengarahkannya ke / dev / null , misalnya:

su someuser -c "some_script.sh 0<&- 1>&- 2>&- &"

0 <& - Menutup input standar (0)
1> & - Menutup output standar (1)
2> & - Menutup kesalahan standar (2) output

Arah tanda <> tidak masalah karena nomor deskriptor file yang panjang ditentukan. Jadi ini sama baiknya:

su someuser -c "some_script.sh 0>&- 1>&- 2>&- &"

atau

su someuser -c "some_script.sh 0<&- 1<&- 2<&- &"

Namun ada cara yang sedikit lebih pendek untuk menulis itu, tanpa angka untuk stdin dan stdout, di mana arah memang penting:

su someuser -c "some_script.sh <&- >&- 2>&- &" 

Ketika file deskriptor ditutup atau dialihkan ke / dev / null ( start-stop-daemon melakukan pengalihan ke / dev / null) proses aman untuk berjalan di latar belakang sebagai daemon. Jadi itulah yang diperlukan untuk menghindari masalah ( startpar ) dengan meluncurkan skrip saat boot.

Saya telah mengimplementasikan seluruh solusi dari ide awal saya dan meletakkannya di GitHub:
https://github.com/ivankovacevic/userspaceServices

Ivan Kovacevic
sumber
Ivan, apakah lebih baik menggunakan su atau su -login? Saya membaca su su tetapi saya tidak mengerti untuk kasus khusus ini.
Massimo
1
@ Massimo, maaf atas keterlambatan tanggapan saya! Lihat pertanyaan ini: unix.stackexchange.com/questions/318572/... ada halaman manual yang lebih baik di sana untuk menjelaskannya. Pada dasarnya perbedaannya adalah dalam mengatur direktori kerja dan variabel lingkungan. Saya akan mengatakan untuk kasus penggunaan seperti ini (melakukan sesuatu sebagai pengguna lain) itu mungkin merupakan pilihan yang lebih baik untuk benar-benar menggunakan -login
Ivan Kovacevic
3

Anda dapat menggunakan start-stop-daemon dari init.d dengan --useropsi.

dmourati
sumber
Saya sudah berkomentar tentang start-stop-daemon pada jawaban Mr Shark dan saya juga membuat pembaruan untuk jawaban saya dan pertanyaan saya (pembaruan 4)
Ivan Kovacevic
2

Saya belum sepenuhnya menguji ini, tapi saya pikir itu seperti:

/sbin/start-stop-daemon --background --start --exec /home/USER/.startUp --user USER --pidfile=/home/USER/.startUp.pid --make-pidfile

saat startup dan kemudian

/sbin/start-stop-daemon --stop --user USER --pidfile=/home/USER/.startUp.pid

saat mematikan.

Menangani skrip .shutDown dapat dilakukan dengan sesuatu seperti hal startup, tetapi Anda tidak dapat memastikan bahwa skrip dijalankan hingga berakhir karena shutdown akan tetap terjadi :-)

harus melakukan trik, mungkin Anda harus memasukkan beberapa pengalihan input, tetapi kemudian Anda harus khawatir tentang file log yang sedang diisi.

Tuan Shark
sumber
2
Intinya, ini akan berhasil! start-stop-daemon dapat menjalankan proses dengan sukses saat boot atau sebaliknya. Saya sudah mengujinya. Dan itu juga menghilangkan masalah itu dengan menggantung proses startpar. Namun, Anda juga tidak memiliki USER - pilihan dalam panggilan awal Anda. Tanpa itu, itu akan meluncurkan proses sebagai root. File pid juga harus ditulis ke / var / run / karena jika tidak menghasilkan file yang dimiliki root di direktori home pengguna. Tapi, dalam pikiranku, untuk peluncuran generik skrip start-stop-daemon tampaknya sedikit berlebihan. Periksa jawaban saya di mana saya mencoba menguraikan mengapa.
Ivan Kovacevic
1

Sudahkah Anda mencoba menggunakan su?

su -c /home/user/.startUp/executable - user

-c memberitahu su untuk mengeksekusi perintah, dan parameter terakhir adalah pengguna untuk menjalankannya sebagai.

Tero Kilkanen
sumber
ya, itu berhasil tetapi dengan beberapa kutipan dan menambahkan ampersand. Dan saya merasa lebih bersih untuk menuliskannya seperti ini: su <username> -c "/some/path/script.sh &" Pada dasarnya saya telah menggunakan sudo karena tampaknya lebih bersih tetapi sekarang ini tampaknya lebih baik daripada menggunakan: sudo - u <username> bash -c "/some/path/script.sh &". Tidak tahu apakah ada perbedaan dalam keduanya
Ivan Kovacevic