Sự khác biệt giữa chương trình khởi động systemd và terminal


9

Tôi tò mò không biết sự khác biệt này là gì giữa các chương trình; bắt đầu với systemd khi được kích hoạt thông qua systemctl, so với những cái được bắt đầu bằng phương tiện /etc/rc.localhoặc thông qua CLI.

Ví dụ, gần đây tôi đã sử dụng shairport-sync cho raspberry pi. Ban đầu, tôi đặt shairport-sync để bắt đầu bằng sudo systemctl kích hoạt shairport-sync.

Sau này, tôi đã sử dụng một chức năng bên trong shairport-syncđể chạy các tập lệnh trước và đăng lên các thiết bị kết nối.

Thật ngạc nhiên, các tập lệnh khi được thực thi bởi shairport-synckhông kill arecordhoặcaplay

Tuy nhiên, khi tôi chạy tập lệnh qua terminal, tập lệnh được thực thi và bị giết arecordaplay.

Để làm tôi bối rối hơn nữa, tôi đã giết shairport-syncvà khởi động nó qua thiết bị đầu cuối để xem kết quả của những gì đang xảy ra. Khi tôi làm như vậy, các kịch bản hoạt động như tôi mong đợi khi thiết bị kết nối và bị giết arecordaplay. Vì vậy, như một sửa chữa tôi bị vô hiệu hóa shairport-synctrong sysmtectlvà đặt để nó chạy trong /etc/rc.localsửa chữa gấp gáp. Sau khi rebootnó hoạt động như tôi mong đợi.

Điều này khiến tôi tin rằng có một số khác biệt giữa chương trình chạy ngoài systemdvà chương trình chạy khi bắt đầu thông qua /etc/rc.localhoặc CLI.

Lý do tại sao điều này xảy ra? Đây có phải là do mức độ chạy khác nhau? Một số ma thuật đen tối?

Kịch bản được chạy khi thiết bị kết nối shairport-syncnhư sau:shairportstart.sh

#!/bin/sh
/usr/bin/sudo /bin/pkill arecord
if [ $(date +%H) -ge "18" -o $(date +%H) -le "7" ]; then
        /usr/bin/amixer set Speaker 40%
else
        /usr/bin/amixer set Speaker 100%
fi
/home/pi/shScripts/shairportfade.sh&

exit 0

Đây là kịch bản mờ dần: shairportfade.sh

#!/bin/sh
/usr/bin/amixer set Speaker 30-
for (( i=0; i<30; i++))
do  
    /usr/bin/amixer set Speaker 1+
done
exit 0

Tập lệnh được chạy khi thiết bị ngắt kết nối shairport-syncnhư sau:shairportend.sh

#!/bin/sh
/usr/bin/amixer set Speaker 70%
/usr/bin/arecord -D plughw:1 -f dat | /usr/bin/aplay -D plughw:1 -f dat&
exit 0

Tôi chỉ tìm thấy lỗi sau /var/log/syslogkhi đồng bộ hóa shairport ban đầu chạy ngoài systemd. Khi shairport-syncđược chạy từ CLI hoặc /etc/rc.localkhông có lỗi.

Jan 24 00:38:45 raspberrypi shairport-sync[617]: sudo: no tty present and no askpass program specified

Xin lưu ý rằng sự khác biệt duy nhất là cách shairport-synckhởi động ban đầu, khi các thiết bị kết nối hoặc ngắt kết nối shairport-synctiếp tục chạy.


1
Đó là ps ... awk ... grep ...những thứ có thể được thay thế bằng một đơn giản hơnpkill
thrig

@thrig ban đầu dòng này đơn giản hơn nhiều nhưng vì nó không hoạt động hoặc vì vậy tôi nghĩ rằng tôi đã thử sử dụng các phương pháp khác để tiêu diệt cá thể vẫn không hoạt động. Giết chết quá trình không phải là vấn đề vì nó đã hoạt động nhưng chỉ khi chạy từ đăng nhập của người dùng
Brett Reinhard

bạn có thể hiển thị danh sách của /home/pi/shScripts/shairportfade.sh?
Michael D.

@MichaelD. tôi đã thêm tập lệnh fade cũng như tập lệnh được thực thi khi thiết bị ngắt kết nối với shairport-sync
Brett Reinhard

@BrettReinhard có vấn đề gì với việc chạy tập lệnh từrc.local
Michael D.

Câu trả lời:


18

Biến thể của "Tại sao mọi thứ hành xử khác nhau theo systemd?" là một câu hỏi thường gặp.

Bất cứ khi nào một cái gì đó chạy từ CLI và không phải từ systemd, có một số loại khả năng rộng lớn để giải thích cho sự khác biệt.

  1. Biến môi trường khác nhau . systemdghi lại các biến môi trường mà nó truyền vào man systemd.exectrong phần Biến môi trường trong các quy trình được sinh ra . Nếu bạn muốn tự kiểm tra sự khác biệt, bạn có thể sử dụng systemd-run /path/to/binary, nó sẽ chạy ứng dụng của bạn trong phạm vi nhất thời, vì nó sẽ được điều hành bởi một dịch vụ systemd. Bạn sẽ nhận được đầu ra như : Running as unit: run-u160.service. Sau đó bạn có thể journalctl -u run-u160.servicexem lại đầu ra. Sửa đổi ứng dụng của bạn để loại bỏ các biến môi trường mà nó nhận được và so sánh chạy CLI với chạy systemd. Nếu ứng dụng không được sửa đổi một cách thuận tiện, bạn chỉ có thể sử dụng systemd-run envđể xem các biến môi trường sẽ được thông qua và xem lại nhật ký nhật ký cho nó. Nếu bạn đang cố gắng khởi động ứng dụng GUI X11, DISPLAYbiến môi trường cần được đặt. Trong trường hợp đó, hãy cân nhắc sử dụng tính năng "tự khởi động" của môi trường máy tính để bàn của bạn thay vì systemd.
  2. Hạn chế về nguồn lực . Xem man systemd.resource-controlcác giá trị cấu hình có thể hạn chế tiêu thụ tài nguyên. Sử dụng systemctl show your-unit-unit.serviceđể kiểm tra các giá trị cấu hình đầy đủ ảnh hưởng đến dịch vụ bạn đang cố gắng bắt đầu.
  3. Vỏ không tương tác . bashMôi trường CLI của bạn là một vỏ đăng nhập tương tác . Nó đã có nguồn gốc file như .bashrcrằng systemdkhông có. Bên cạnh việc đặt các biến môi trường, các tập lệnh này có thể thực hiện bất kỳ số lượng nào khác, chẳng hạn như kết nối một tác nhân SSH để các hành động SSH không yêu cầu đăng nhập. Xem thêm Sự khác biệt giữa Shell đăng nhập và Shell không đăng nhập?
  4. Không có TTY . Phiên tương tác của bạn được kết nối với TTY mà một số chương trình thích sudosshmong đợi khi nhắc mật khẩu. Xem thêm sudo: không có tty hiện tại và không có chương trình hỏi
  5. Đường dẫn tương đối so với tuyệt đối . Công cụ nhị phân tương đối hoạt động trong hệ vỏ, nhưng như được ghi lạiman systemd.service , đối số đầu tiên ExecStart=phải là một đường dẫn tuyệt đối đến nhị phân.
  6. Cú pháp dòng lệnh bị hạn chế . Shell CLIs hỗ trợ nhiều siêu ký tự, trong khi systemdcó cú pháp dòng lệnh rất hạn chế . Tùy thuộc vào nhu cầu của bạn, bạn có thể sao chép cú pháp Shell systemdbằng cách chạy rõ ràng lệnh của bạn thông qua trình bao:ExecStart=/bin/bash -c '/my/bash $(syntax) >/goes-here.txt'

Đây là một tính năng mà hệ thống chạy mã của bạn trong một môi trường nhất quán với các điều khiển tài nguyên. Điều này giúp cho kết quả ổn định, có thể tái tạo trong thời gian dài mà không áp đảo phần cứng.


Cũng cần phải tính đến bối cảnh MAC (SELinux, ...), khả năng, không gian tên ...
Bigon

2
@BrettReinhard Đừng gọi sudoscript shell chạy tốt hơn sudo shairportstart.shtừ terminal, vì systemd đang chạy script dưới dạng root, không cần sudo là root.
Michael D.

1
Tôi đã giải quyết vấn đề của mình bằng nhiều cách để cố gắng hiểu chuyện gì đang xảy ra. Cuối cùng, những gì tôi đã làm là thay đổi lệnh giết của tôi thành /usr/bin/echo "mypassword" | /usr/bin/sudo /bin/pkill arecord. Sau này vào ngày hôm nay, tôi sẽ thử loại bỏ các lệnh sudoecholệnh thành lệnh kill của tôi và xem liệu điều đó có mang lại kết quả tương tự không. Tôi đoán là nó sẽ hoạt động, vì có vẻ như lỗi là do không có mật khẩu được gửi bằng sudolệnh. Cảm ơn bạn đã giúp đỡ để hiểu lý do tại sao có sự khác biệt giữa systemdvà CLI
Brett Reinhard

1
Một sự khác biệt khác, có thể rõ ràng nhưng ngày nay tôi thấy, đó là systemd cố gắng theo dõi trạng thái của một dịch vụ và sẽ không khởi động nó nếu nó nghĩ rằng nó đã hoạt động, vì vậy nó thậm chí không thể khởi chạy một tập lệnh init.d nếu nó nghĩ rằng dịch vụ đang chạy. Ngược lại, các tập lệnh init.d thường được viết để luôn kiểm tra và cố gắng khởi động dịch vụ khi thích hợp.
Josh Kelley

1
@JoshKelley Cảm ơn vì tiền boa. Đó không phải là một sự khác biệt giữa systemd và CLI mà là giữa các script init.d của systemd và sysVinit.
Mark Stosberg
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.