Bắt đầu một tập lệnh như một người dùng khác


12

Tôi đã tạo một tập lệnh trong /etc/init.d/ để chạy một số tập lệnh khác từ những người dùng khác (không có quyền root) từ thư mục chính của họ, như thể họ đã khởi động chúng.

Tôi khởi chạy các tập lệnh này với: sudo -b -u <username> <script_of_a_particular_user>

Và nó hoạt động. Nhưng đối với mọi tập lệnh người dùng tiếp tục chạy (ví dụ như một số watchdog) tôi thấy một quá trình sudo cha tương ứng, vẫn còn sống và chạy như root. Điều này tạo ra một mớ hỗn độn trong danh sách các quy trình hoạt động.

Vì vậy, câu hỏi của tôi là: Làm thế nào tôi có thể khởi chạy (fork) một tập lệnh khác từ tập lệnh bash hiện có với tư cách là một người dùng khác và để nó như một quá trình mồ côi (độc lập)?

Giải thích chi tiết hơn:
Về cơ bản, tôi đang cố gắng cung cấp cho người dùng khác trên máy một phương tiện để chạy công cụ khi khởi động hệ thống hoặc tắt hệ thống bằng cách chạy các tệp thực thi được tìm thấy trong thư mục con tương ứng được tìm thấy trong thư mục chính của họ, có tên .startUp và .shutDown. Vì tôi không tìm thấy bất kỳ phương tiện nào khác để làm điều đó nên tôi đã viết tập lệnh bash của mình, chính xác là nó và tôi đã cấu hình nó như một tập lệnh dịch vụ (bằng cách làm theo ví dụ về bộ xương) trong /etc/init.d/ để khi nó được chạy với đối số bắt đầu, nó khởi chạy mọi thứ từ các thư mục .startUp và khi nó được chạy với đối số dừng, nó khởi chạy mọi thứ từ các thư mục .shutDown của tất cả người dùng như chúng.

Ngoài ra, tôi cũng quan tâm nếu tôi có thể sử dụng một số giải pháp hiện có để giải quyết vấn đề này.

CẬP NHẬT
Tôi đã xem xét xung quanh một chút và tôi tìm thấy câu hỏi này: /unix/22478/detach-a-daemon-USE-sudo

Chấp nhận câu trả lời ở đó, để sử dụng : sudo -u user sh -c "daemon & disown %1", hoạt động cho tôi. Nhưng tôi cũng đã thử mà không từ chối% 1 và nó cũng như vậy. Vì vậy, đây là những gì làm việc cho tôi như tôi mong đợi:

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

Câu hỏi bổ sung của tôi bây giờ là, tại sao nó hoạt động mà không bị từ chối? Tôi vẫn nên rời khỏi cuộc gọi từ chối , bất kể, đối với một số trường hợp đặc biệt tiềm năng?

CẬP NHẬT 2

Rõ ràng điều này cũng hoạt động:

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

Có sự khác biệt nào giữa cuộc gọi này và cuộc gọi sudo không? Tôi biết đây có khả năng là một câu hỏi hoàn toàn khác. Nhưng vì tôi đang tìm câu trả lời ở đây, có lẽ vì lợi ích của chủ đề này, ai đó có thể làm rõ điều này ở đây.

CẬP NHẬT 3
Cả hai phương thức này với su hoặc sudo hiện tạo ra một quy trình startpar mới (quy trình đơn chạy dưới dạng root) sau khi tôi khởi động máy. Hiển thị trong danh sách quy trình như:

startpar -f -- <name_of_my_init.d_script>

Tại sao quá trình này sinh sản? Rõ ràng là tôi đang làm gì đó sai vì không có tập lệnh init.d nào khác có quá trình này chạy.

CẬP NHẬT 4
Vấn đề với startpar được giải quyết. Tôi đã bắt đầu một câu hỏi khác cho điều đó:
quá trình startpar bị treo khi bắt đầu các quy trình từ RC.local hoặc init.d

Và một câu hỏi khác để thảo luận thêm về các cơ chế khởi chạy cho người dùng không có đặc quyền:
Cung cấp cho người dùng bình thường (không phải root) khả năng khởi động và tắt tự động

Câu trả lời:


18

Câu trả lời chính xác cho điều này là để "daemonization" thích hợp, đầu vào tiêu chuẩn, đầu ra tiêu chuẩn và lỗi tiêu chuẩn cần phải được chuyển hướng đến / dev / null (hoặc một số tệp thực):

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

su - thay thế danh tính người dùng cho đối số someuser
-c - su để chạy lệnh được chỉ định
nohup - Chạy lệnh miễn dịch với hangouts. Để ngăn chặn các trường hợp trong đó quá trình cha mẹ sẽ chấm dứt quá trình con. Thêm vào đây chỉ trong trường hợp. Nhưng thực sự không có tác dụng trong trường hợp cụ thể của tôi. Có cần thiết hay không phụ thuộc vào môi trường (kiểm tra shopt )
> / dev / null - Chuyển hướng đầu ra tiêu chuẩn thành không có gì, về cơ bản là vô hiệu hóa nó.
2> & 1 - Chuyển hướng lỗi tiêu chuẩn (2) sang đầu ra tiêu chuẩn (1), được chuyển hướng thành null
& - tách ra nền, điều này cũng sẽ chuyển hướng đầu vào tiêu chuẩn sang / dev / null.

Đây thực chất là chính xác những gì tiện ích start-stop-daemon từ Debian dpkg làm ở lõi của nó. Đó là lý do tại sao tôi thích bắt đầu các tập lệnh theo cách này hơn là giới thiệu một cuộc gọi tiện ích bên ngoài khác trong mã của mình. start-stop-daemon rất hữu ích trong trường hợp bạn có các chương trình daemon đầy đủ mà bạn cần bắt đầu và khi đó bạn cần thêm chức năng mà start-stop-daemon cung cấp (ví dụ: kiểm tra xem quy trình đã chỉ định có đang chạy chưa Sẽ khởi động lại lần nữa).

Cũng đáng lưu ý rằng bạn cũng có thể đóng các mô tả tệp của quy trình của mình thay vì chuyển hướng chúng sang / dev / null , ví dụ:

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

0 <& - Đóng đầu vào tiêu chuẩn (0)
1> & - Đóng đầu ra tiêu chuẩn (1)
2> & - Đóng đầu ra lỗi tiêu chuẩn (2)

Hướng của dấu <> không quan trọng vì số mô tả tệp dài được chỉ định. Vì vậy, điều này là tốt như nhau:

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

hoặc là

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

Tuy nhiên, có một cách ngắn hơn để viết rằng, không có số cho stdin và stdout, trong đó hướng quan trọng:

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

Khi các bộ mô tả tệp được đóng hoặc chuyển hướng đến / dev / null ( start-stop-daemon đang thực hiện chuyển hướng đến / dev / null), quy trình sẽ an toàn để chạy trong nền dưới dạng daemon. Vì vậy, đó là những gì cần thiết để tránh các vấn đề ( startpar ) với việc khởi chạy các tập lệnh trong thời gian khởi động.

Tôi đã triển khai toàn bộ giải pháp từ ý tưởng ban đầu của mình và đặt nó trên GitHub:
https://github.com/ivankovacevic/userspaceService


Ivan, tốt hơn là sử dụng su hoặc su -login? Tôi đọc người đàn ông của su nhưng tôi không thể hiểu cho trường hợp cụ thể này.
Massimo

1
@Massimo, xin lỗi vì sự chậm trễ trong phản hồi của tôi! Kiểm tra câu hỏi này: unix.stackexchange.com/questions/318572/ Khăn có một trang hướng dẫn tốt hơn ở đó giải thích nó. Về cơ bản sự khác biệt là trong việc thiết lập các biến môi trường và thư mục làm việc. Tôi muốn nói với những trường hợp sử dụng như thế này (làm một cái gì đó với tư cách là một người dùng khác) thì đó có thể là một lựa chọn thích hợp hơn để thực sự sử dụng -login
Ivan Kovacevic

3

Bạn có thể sử dụng start-stop-daemon trong init.d với --usertùy chọn.


Tôi đã nhận xét về start-stop-daemon về câu trả lời của Mr Shark và tôi cũng đã cập nhật câu trả lời của mình và câu hỏi của tôi (cập nhật 4)
Ivan Kovacevic

2

Tôi chưa kiểm tra đầy đủ điều này, nhưng tôi nghĩ rằng một cái gì đó như:

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

lúc khởi động và sau đó

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

khi tắt máy

Xử lý tập lệnh .shutDown có thể được thực hiện bằng một cái gì đó giống như điều khởi động, nhưng bạn không thể chắc chắn rằng các tập lệnh chạy để kết thúc kể từ khi tắt máy sẽ xảy ra bằng mọi cách :-)

Nên thực hiện thủ thuật, có lẽ bạn nên đưa vào một số chuyển hướng đầu vào, nhưng sau đó bạn sẽ phải lo lắng về việc các tệp nhật ký được điền.


2
Về cơ bản, điều này sẽ làm việc! start-stop-daemon có thể khởi chạy các tiến trình thành công khi khởi động hoặc nếu không. Tôi đã thử nó. Và nó cũng được loại bỏ vấn đề đó với quy trình treo startpar. Tuy nhiên, bạn cũng đang thiếu một NGƯỜI DÙNG - trong cuộc gọi bắt đầu của bạn. Không có nó, nó sẽ khởi chạy tiến trình như root. Tệp pid có lẽ cũng nên được ghi vào / var / run / vì nếu không, nó sẽ tạo một tệp sở hữu gốc trong thư mục chính của người dùng. Nhưng, trong suy nghĩ của tôi, đối với kịch bản chung khởi chạy start-stop-daemon dường như là một chút quá mức. Kiểm tra câu trả lời của tôi, nơi tôi đã cố gắng giải thích tại sao.
Ivan Kovacevic

1

Bạn đã thử sử dụng su?

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

-c yêu cầu su thực thi lệnh và tham số cuối cùng là người dùng thực thi lệnh đó.


vâng, nó hoạt động nhưng với một số trích dẫn và thêm dấu và. Và tôi thấy nó sạch hơn khi viết nó như vậy: su <tên người dùng> -c "/some/path/script.sh &" Về cơ bản tôi đã sử dụng sudo vì nó có vẻ sạch hơn nhưng bây giờ điều này có vẻ tốt hơn khi sử dụng: sudo - u <tên người dùng> bash -c "/some/path/script.sh &". Không biết có sự khác biệt nào trong hai điều đó không
Ivan Kovacevic
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.