Viết một dịch vụ phụ thuộc vào Xorg


30

Tôi đang cố gắng viết một dịch vụ cấp độ người dùng redshiftvà nó cần đợi cho đến khi Xorg hoạt động. Tệp dịch vụ hiện tại của tôi trông như thế này:

[Unit]
Description=Redshift
After=graphical.target

[Service]
Environment=DISPLAY=:0
ExecStart=/bin/redshift -l 28:-13 -t 5300:3300 -b 0.80:0.91 -m randr
Restart=always

[Install]
WantedBy=default.target

Tuy nhiên, có vẻ như nó cố gắng bắt đầu trước khi Xorg hoạt động và tôi phải tự khởi động dịch vụ sau đó. Tôi đoán tôi đang sử dụng sai After=mục tiêu. Có gợi ý nào không?

Câu trả lời:


20

Tôi đã nghiên cứu điều này và câu trả lời của grawity dường như đã lỗi thời. Bây giờ bạn có thể thiết lập các dịch vụ người dùng với systemd chạy với một phần của phiên người dùng. Họ có thể có bộ HIỂN THỊ và XAUTHORITY (hiện đang ở Arch và Debian Stretch).

Điều này có ý nghĩa đối với các đề xuất trước đây về việc sử dụng các tệp tự khởi động trên máy tính để bàn, khi bạn nhận được quản lý quy trình giống như bạn sẽ làm một ứng dụng cấp hệ thống (khởi động lại, v.v.).

Tài liệu tốt nhất hiện nay là wiki wiki; Hệ thống / người dùng

Phiên bản TLDR;

  1. Tạo tệp * .service mong muốn trong ~/.config/systemd/user/
  2. Chạy systemctl --user enable [service](loại trừ hậu tố dịch vụ)
  3. Tùy chọn chạy systemctl --user start [service]để bắt đầu ngay bây giờ
  4. Sử dụng systemctl --user status [service]để kiểm tra xem nó đang hoạt động như thế nào

Một vài lệnh hữu ích khác.

  • systemctl --user list-unit-files - xem tất cả các đơn vị người dùng
  • s ystemctl --user daemon-reload- nếu bạn chỉnh sửa tệp .service

-- Một lát sau...

Tôi đã nâng cấp và chuyển đổi hầu hết các trình tiện ích phiên của mình sang các tệp systemd .service. Vì vậy, tôi có thể thêm một vài ghi chú bổ sung.

Không có hook mặc định để chạy các dịch vụ khi đăng nhập, vì vậy bạn phải tự kích hoạt nó. Tôi làm điều đó từ tập tin ~ / .xsession của tôi.

systemctl --user import-environment PATH DBUS_SESSION_BUS_ADDRESS
systemctl --no-block --user start xsession.target

Dòng đầu tiên nhập một số biến môi trường vào phiên người dùng systemd và dòng thứ hai khởi động mục tiêu. Tệp xsession.target của tôi;

[Unit]
Description=Xsession running
BindsTo=graphical-session.target

Xbindkeys.service của tôi là một ví dụ.

[Unit]
Description=xbindkeys
PartOf=graphical-session.target

[Service]
ExecStart=/usr/bin/xbindkeys -n -f ${HOME}/projects/dotfiles/.xbindkeysrc
Restart=always

[Install]
WantedBy=xsession.target

2
Nếu bạn có thể cung cấp một tệp đơn vị mẫu và giải thích làm thế nào để đơn vị có thể sử dụng HIỂN THỊ và XAUTHORITY, tôi sẽ vui lòng chuyển câu trả lời được chấp nhận.
mkaito

@mkaito Tôi sẽ xem xét điều đó một khi Debian phát hành Stretch. Tôi đang chạy Debian ổn định và đợi đến lúc đó để chơi với nó nhiều hơn.
John Eikenberry

@mkaito Tại github.com/systemd/systemd/blob/v219/NEWS#L194 nó nói "Một X11 phiên scriptlet hiện đang vận chuyển đó upload $ DISPLAY và $ XAUTHORITY vào môi trường của systemd --user daemon nếu phiên bắt đầu. Điều này sẽ cải thiện khả năng tương thích với các ứng dụng hỗ trợ X11 chạy dưới dạng dịch vụ người dùng systemd. "
josch

Tôi vẫn muốn xem một tập tin đơn vị mẫu, chỉ để làm cho nó rõ ràng nếu có bất cứ điều gì đặc biệt cần thiết.
mkaito

11

Gợi ý thông thường là "không". redshiftkhông phải là một dịch vụ toàn hệ thống - nó sẽ có một phiên bản riêng cho mỗi phiên và nó cần biết về cách kết nối với Xorg của phiên cụ thể đó.

(Xorg cũng không phải là dịch vụ hệ thống - chỉ có trình quản lý hiển thị và nó cũng khởi chạy một Xorg riêng cho mỗi phiên. // graphical.targetsẽ cho bạn biết khi nào trình quản lý hiển thị sẵn sàng, nhưng nó không nói gì khi DM thực sự khởi động đầu tiên - hoặc tất cả - hiển thị.)

Chỉ khởi động nó khi khởi động với DISPLAY=:0nó là không đủ, vì không có gì đảm bảo rằng có chính xác một màn hình hiển thị tại bất kỳ thời điểm nào, cũng không phải lúc nào cũng vậy :0(ví dụ: nếu Xorg gặp sự cố để lại một lockfile cũ, thì cái tiếp theo sẽ chạy :1theo sẽ nghĩ :0là vẫn bị chiếm đóng); bạn cũng cần đặt đường dẫn đến XAUTHORITYtệp của mình vì X11 yêu cầu xác thực; và đảm bảo redshiftđược khởi động lại nếu bạn đăng xuất và đăng nhập lại.

Vậy làm thế nào để bắt đầu nó? Hầu như luôn luôn, môi trường máy tính để bàn có một số phương pháp để bắt đầu các dịch vụ phiên của riêng nó . Xem một bài viết cũ hơn đã mô tả hai bài viết thông thường; các ~/.xprofilekịch bản và các ~/.config/autostart/*.desktopđịa điểm.

Nếu bạn sử dụng startx , bạn có thể sử dụng ~/.xinitrcđể bắt đầu những thứ như vậy. Các trình quản lý cửa sổ độc lập thường có các tập lệnh khởi động / init riêng; ví dụ ~/.config/openbox/autostartcho Openbox.

Điều chung cho tất cả các phương pháp này là chương trình được bắt đầu từ trong phiên - tránh tất cả các vấn đề được liệt kê ở trên.


Mặc dù redshift không phải là một dịch vụ toàn hệ thống trong nhiều trường hợp, nó có ý nghĩa là một dịch vụ người dùng, đó chính xác là những gì OP đang cố gắng thực hiện.
simotek

5

Đây là những gì tôi vừa tạo như một cách giải quyết chưa có sẵn graphical-session.target(Trên hệ thống Kubfox 16.04 của tôi):

  1. Tạo một đơn vị người dùng hệ thống giả , đưa lên và xuống đồ họa.

Tạo ~/.config/systemd/user/xsession.targetvới nội dung sau:

[Đơn vị]
Mô tả = Xsession lên và chạy
BindsTo = Graphics-session.target

Nói với systemd về đơn vị mới này:

$> systemctl --user daemon-reload
  1. Tạo các kịch bản tự khởi động và tắt máy điều khiển xsession.targetthông qua các cơ chế hiện có của máy tính để bàn Ubuntu 16.04.

Tạo ~/.config/autostart-scripts/xsession.target-login.shvới nội dung sau:

#! / bin / bash

nếu ! systemctl --user đang hoạt động xsession.target &> / dev / null
sau đó
  / bin / systemctl - môi trường nhập khẩu người dùng HIỂN THỊ XAUTHORITY
  / bin / systemctl - người dùng bắt đầu xsession.target
fi

Tạo ~/.config/plasma-workspace/shutdown/xsession.target-logout.shvới nội dung sau:

#! / bin / bash

nếu systemctl --user đang hoạt động xsession.target &> / dev / null
sau đó
  / bin / systemctl - người dùng dừng xsession.target
fi

Làm cho các kịch bản thực thi:

$> chmod + x ~ / .config / autostart-scripts / xsession.target-login.sh
$> chmod + x ~ / .config / plasma-workspace / shutdown / xsession.target-logout.sh

Lưu ý: hai tệp này được đặt trong đó KDE sẽ chọn chúng để tự khởi động và tắt máy. Các tệp có thể được đặt ở một nơi khác cho các môi trường máy tính để bàn khác (ví dụ Gnome) - nhưng tôi không biết về các môi trường đó.

Lưu ý: Cách giải quyết này thiếu hỗ trợ của nhiều phiên máy tính để bàn. Nó chỉ xử lý graphical-session.targetchính xác miễn là chỉ có một phiên X11 hoạt động được chạy trên máy (nhưng đó là trường hợp của hầu hết người dùng linux của chúng tôi).

  1. Tạo các đơn vị người dùng systemd của riêng bạn phụ thuộc vào graphical-session.targetvà để chúng chạy sạch trong khi đăng nhập trên máy tính để bàn của bạn.

Ví dụ, đơn vị của @ mkaito sẽ trông như thế này:

[Đơn vị]
Mô tả = Dịch chuyển đỏ
PartOf = Graphics-session.target

[Dịch vụ]
ExecStart = / bin / dịch chuyển đỏ -l 28: -13 -t 5300: 3300 -b 0,80: 0,91 -m randr
Khởi động lại = luôn

(Đừng quên làm daemon-reloadsau khi chỉnh sửa các đơn vị của bạn!)

  1. Khởi động lại máy của bạn, đăng nhập và xác minh các đơn vị của bạn được bắt đầu như mong đợi
$> systemctl - đồ họa trạng thái người dùng-session.target
● Graphics-session.target - Phiên người dùng đồ họa hiện tại
   Đã tải: đã tải (/usr/lib/systemd/user/graphical-session.target; static; nhà cung cấp cài sẵn: đã bật)
   Hoạt động: hoạt động kể từ Don 2017-01-05 15:08:42 CET; 47 phút trước
     Tài liệu: người đàn ông: systemd.special (7)
$> systemctl - người dùng trạng thái đơn vị của bạn ...

Vào một ngày nào đó trong tương lai (sẽ là Ubuntu 17.04?) Cách giải quyết của tôi trở nên lỗi thời vì hệ thống sẽ tự xử lý graphical-session.targetchính xác. Vào ngày đó, chỉ cần xóa tập lệnh tự khởi động và tắt máy và cả xsession.target- các đơn vị người dùng tùy chỉnh của bạn có thể không bị ảnh hưởng và chỉ hoạt động.


Tôi biết đây là một nhận xét cũ nhưng bạn cũng có thể thêm các tập lệnh khởi động / đăng nhập thông qua ứng dụng Cài đặt hệ thống trong Workspace> Khởi động và Tắt máy> Tự động khởi động, nếu bạn muốn đặt các tập lệnh đó vào một nơi bạn sẽ nhớ chúng.
AmbientCyan

2

Giải pháp này thực hiện chính xác những gì tác giả của câu hỏi yêu cầu:

nó cần đợi cho đến khi Xorg hoạt động

Mặc dù có thể có những cách tốt hơn để làm điều đó, như đã được trả lời bởi những người dùng khác, đây là một cách tiếp cận khác cho vấn đề này.

Nó tương tự như systemd-networkd-Wait-online.service chặn cho đến khi các tiêu chí nhất định được đáp ứng. Các dịch vụ khác phụ thuộc vào nó sẽ được triển khai ngay khi dịch vụ này bắt đầu thành công hoặc hết thời gian.

Theo hướng dẫn (phần "Tệp"), máy chủ X sẽ tạo một ổ cắm UNIX /tmp/.X11-unix/Xn(trong đó ncó số hiển thị).

Bằng cách theo dõi sự hiện diện của ổ cắm này, chúng tôi có thể xác định rằng máy chủ cho màn hình cụ thể đã bắt đầu.

confirm_x_started.sh:

#!/bin/bash
COUNTER=0

while [ 1 ]
do
  # Check whether or not socket exists
  if [ -S /tmp/.X11-unix/X0 ]
  then
    exit 0
  fi

  ((++COUNTER))

  if [ $COUNTER -gt 20 ]
  then
    exit 1
  fi

  sleep 0.5
done

x_server_started.service:

[Unit]
Description=Monitor X server start

[Service]
Type=oneshot
ExecStart=/path/to/confirm_x_started.sh

[Install]
WantedBy=example.target

Bây giờ, kích hoạt x_server_started.serviceđể bắt đầu cùng lúc với máy chủ X.

Làm cho các dịch vụ khác (cần khởi động máy chủ X) để phụ thuộc vào x_server_started.service

đơn vị phụ thuộc:

[Unit]
Description=Service that needs to have the X server started
Requires=x_server_started.service
After=x_server_started.service

[Service]
ExecStart=/path/to/binary

[Install]
WantedBy=example.target

Nếu máy chủ X khởi động mà không gặp sự cố, thiết bị x_server_started.servicesẽ khởi động gần như ngay lập tức và systemd sẽ tiến hành khởi động tất cả các đơn vị phụ thuộc vào x_server_started.service.


Điều này hoạt động độc đáo. Các dịch vụ bổ sung là một liên lạc tốt đẹp. Bạn cũng có thể chỉ sử dụng ExecStartPre trong dịch vụ mục tiêu của mình. Tôi đã phải thêm một 'ngủ 1' trước khi 'thoát 0', có vẻ như hơi quá nhanh để chỉ cần thử và bắt X ngay lập tức.
TTimo
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.