Cách thích hợp của người Viking để kiểm tra xem một dịch vụ có đang chạy trong một tập lệnh không


96

Vấn đề của tôi:

Tôi đang viết một tập lệnh bash và trong đó tôi muốn kiểm tra xem một dịch vụ cụ thể có đang chạy hay không.

Tôi biết làm thế nào để làm điều này bằng tay, với $ service [service_name] status.

Nhưng (đặc biệt là từ khi chuyển sang systemd), nó in ra cả đống văn bản hơi lộn xộn để phân tích. Tôi giả sử có một lệnh được tạo cho các tập lệnh có đầu ra đơn giản hoặc giá trị trả về mà tôi có thể kiểm tra.

Nhưng Googling xung quanh chỉ mang lại một tấn ps aux | grep -v grep | grep [service_name]kết quả "Ồ, chỉ ". Đó không phải là cách thực hành tốt nhất, phải không? Điều gì xảy ra nếu một phiên bản khác của lệnh đó đang chạy, nhưng không phải là một phiên bản bắt đầu bởi tập lệnh init SysV?

Hay tôi chỉ nên im lặng và làm bẩn tay với một chút pgrep?

Câu trả lời:


140

systemctlcó một is-activetiểu ban cho việc này:

systemctl is-active --quiet service

sẽ thoát với trạng thái 0 nếu servicehoạt động, khác không, làm cho nó lý tưởng cho các tập lệnh:

systemctl is-active --quiet service && echo Service is running

Nếu bạn bỏ qua --quietnó cũng sẽ xuất trạng thái hiện tại thành đầu ra tiêu chuẩn của nó.

Như don_crissti đã chỉ ra , một số đơn vị có thể hoạt động mặc dù không có gì đang chạy để cung cấp dịch vụ: các đơn vị được đánh dấu là RemainAfterExitiến được coi là hoạt động nếu họ thoát thành công, ý tưởng là họ cung cấp dịch vụ không cần daemon ( ví dụ họ cấu hình một số khía cạnh của hệ thống). Tuy nhiên, các đơn vị liên quan đến trình nền sẽ chỉ hoạt động nếu trình nền vẫn đang chạy.


Cẩn thận về các dịch vụ oneshot. Họ chỉ inactivehoặc activatingvà cả hai systemctl statussystemctl is-activethoát với 3. (kể từ systemd-241 ) Cách giải quyết:systemctl show service | grep -qx ActiveStatus=activating
Alois Mahdal

@Alois Tôi đang tự hỏi loại kịch bản nào bạn gặp phải khi muốn xem dịch vụ oneshot đang hoạt động; bạn có một ví dụ không?
Stephen Kitt

Chắc chắn rồi, @StephenKitt. Công cụ foothực hiện một số thứ cho hệ thống liên quan đến khởi động lại và sử dụng dịch vụ one-shot, foo_cleanupở lần khởi động tiếp theo để dọn dẹp mọi thứ. Tôi đang thử nghiệm điều này (tập lệnh của tôi cũng được lên lịch như một dịch vụ) và muốn thu thập lỗi sau đó, nhưng khi nào thì sau đó (nhạc vsauce)? Vâng, một trong những tiêu chí là foo_cleanupđã hoàn thành ("ngừng hoạt động").
Alois Mahdal

Có thể đáng để chỉ ra rằng 'thất bại' cũng là một tùy chọn và rất hữu ích nếu bạn cần thực hiện một hành động dựa trên dịch vụ chưa bắt đầu.
Phill Healey

33

systemctlkhông có chế độ phù hợp cho kịch bản; sử dụng showthay vì statusvà thêm -p/ --properties--valuecác tùy chọn để chỉ nhận đầu ra bạn muốn.

Đây là một ví dụ (từ hệ thống Ubuntu 17.04):

$ systemctl show -p SubState --value NetworkManager
running

Chạy (hoặc cách khác) là một SubState. Nếu bạn muốn biết liệu một dịch vụ có hoạt động hay không, hãy sử dụng thuộc tínhActiveState

$ systemctl show -p ActiveState --value x11-common
inactive
$ systemctl show -p SubState --value x11-common
dead

Ghi chú từ man:

show [PATTERN...|JOB...]
           Show properties of one or more units, jobs, or the manager
           itself. If no argument is specified, properties of the
           manager will be shown. If a unit name is specified, properties
           of the unit are shown, and if a job ID is specified,
           properties of the job are shown. By default, empty properties
           are suppressed. Use --all to show those too. To select specific
           properties to show, use --property=. This command is intended
           to be used whenever computer-parsable output is required. Use
           status if you are looking for formatted human-readable output.

-p, --property=
           When showing unit/job/manager properties with the show command,
           limit display to properties specified in the argument. The
           argument should be a comma-separated list of property names,
           such as "MainPID". Unless specified, all known properties are
           shown. If specified more than once, all properties with the
           specified names are shown. Shell completion is implemented for
           property names.

--value
           When printing properties with show, only print the value, and
           skip the property name and "=".

2
+1 cho câu trả lời tinh vi. vui lòng chỉ định các distro sẽ chấp nhận --versiontùy chọn với systemctl.
SK Venkat

11

Để bổ sung cho câu trả lời của Zanna, --valuetùy chọn cho systemctl showđã được giới thiệu với phiên bản 230 của systemd . Vì vậy, nó có thể không có sẵn trên một số distro nhất định như debian jessie.

Trong trường hợp này, người ta có thể mô phỏng tùy chọn bằng cách sử dụng sed:

$ systemctl show -p ActiveState sshd | sed 's/ActiveState=//g'
active
$ systemctl show -p SubState sshd | sed 's/SubState=//g'  
running

1
+1 để chỉ ra phiên bản giới thiệu & giá trị giới thiệu - giá trị sẽ không hoạt động.
SK Venkat

3

tôi thấy điều này hữu ích cho việc thực thi dòng lệnh hoặc nếu bạn đang tạo tập lệnh.

Sao chép từ @StephenKitt

Điều này sẽ kiểm tra nếu dịch vụ ngừng hoạt động và thực hiện khởi động lại dịch vụ

systemctl is-active --quiet <service name> || <service name> restart

các ||có kiểm tra nếu giá trị trả về từ systemctl là khác không có ý nghĩa nếu nó không hoạt động như giải thích của tác giả.


Bạn cũng có thể sử dụng `is-fail" để kiểm tra nếu cần khởi động lại. Có vẻ như một chút trực quan hơn để khởi động lại một dịch vụ thất bại.
Phill Healey

vâng, nhưng đối với tôi .. tôi muốn thực hành bản thân và cho rằng mọi thứ đang chạy khi nó không. vì vậy tôi có thể đi xác minh những thứ khác với nó. chỉ đơn giản là nếu bạn chỉ muốn kiểm tra nếu nó không chạy, thì 'is-fail' là một lựa chọn đúng đắn. :)
dấu hoa thị

3


Tôi quá muộn để đảng, tuy nhiên sử dụng systemctl là chủ động cùng với &&||để này trong kịch bản sẽ không phải là trường hợp tất cả các thời gian. Dưới đây là một cái tôi đã sử dụng cho tomcat nhưng có thể sử dụng nó trong phương thức lấy các đối số và chuyển tên dịch vụ làm đối số nếu bạn phải kiểm tra nhiều dịch vụ nhưng nó nằm ngoài phạm vi ở đây.

STATUS=`systemctl is-active tomcat.service`
  if [[ ${STATUS} == 'active' ]]; then
    echo "Execute your tasks ....."
  else 
    echo " Service not running.... so exiting "  
    exit 1  
  fi

Đây là cách tôi sử dụng .... Chỉ cần chia sẻ của tôi.

và để đơn giản và dễ dàng, hãy làm theo những người khác giải thích ở đây:

systemctl -q is-active tomcat.service  && echo "Tomcat Runnung" || echo "Service is not running at all "

Làm thế nào là tốt hơn đơn giản if systemctl is-active --quiet tomcat.service? Ngoài ra, [[không phải là vỏ tiêu chuẩn.
Toby Speight

@TobySpeight Bạn cần đọc bài viết của tôi nhiều hơn một chút như tôi đã đề cập trong bài đăng của mình "Đây là cách tôi sử dụng .... Chỉ cần chia sẻ của tôi." Tôi chưa bao giờ nói, đó là cách sử dụng shell tiêu chuẩn, nếu bạn đặt nó trong một dấu ngoặc đơn, nó sẽ trở thành sau đó nhưng nằm ngoài phạm vi ở đây. Ngoài ra, tôi dưới đây đề cập đến việc sử dụng một dòng dễ dàng để làm điều đó bằng cách sử dụng &&||.
SAGAR Nair

2

Thay vì sử dụng lệnh sed như trong câu trả lời của Oxmel, nó đủ để sử dụng cut -d'=' -f 2cho tất cả các loại thuộc tính được truy vấn:

ví dụ:

$ systemctl show -p ActiveState sshd | cut -d'=' -f2
active
$ systemctl show -p SubState sshd | cut -d'=' -f2
running

Điều đó thật tuyệt nhưng bạn thực sự cần đưa ra một số lời giải thích về những gì các lệnh đó làm.
Phill Healey

-1

Vừa tìm thấy kịch bản nhỏ tuyệt vời này:

#!/bin/bash
service=replace_me_with_a_valid_service

if (( $(ps -ef | grep -v grep | grep $service | wc -l) > 0 ))
then
  echo "$service is running!!!"
else
  /etc/init.d/$service start
fi

Nguồn


Không phải tất cả các dịch vụ đều có một tệp thực thi cùng tên và bất kỳ người dùng nào cũng có thể đang chạy một lệnh vô tình khớp - đây là một công thức cho thảm họa.
Toby Speight
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.