Nhật ký đầu ra của tập lệnh nền hoặc khởi động


10

Tôi có một đoạn script ngắn được thực thi bởi một daemon hệ thống cho các sự kiện cụ thể. Tôi biết sự kiện đang xảy ra và kịch bản đang thực thi, nhưng nó không làm những gì tôi dự định. Thật kỳ lạ, nó làm khi tôi chạy nó bằng tay, vì vậy tôi rất bối rối.

Làm thế nào tôi có thể tìm ra những gì đang xảy ra? Kịch bản về cơ bản là một chuỗi các lệnh như thế này:

/bin/foo on 3
sudo bar a

Tôi hiểu điều này được dự định là một hướng dẫn về gỡ lỗi các kịch bản hệ thống, nhưng hơi quá U&L. Tôi đã đọc sai tiêu đề và sẽ đề xuất "Ghi nhật ký đầu ra của tập lệnh hệ thống để gỡ lỗi" sẽ làm cho mục đích rõ ràng hơn. Ngoài ra não của tôi đóng băng khi tôi đọc những foo barví dụ này , tôi thích cái gì đó trông giống thế giới thực hơn. Tôi miễn cưỡng chỉnh sửa bất kỳ bài đăng nào, vì vậy sẽ để lại cho bạn nếu bạn nghĩ nó có thể được cải thiện.
Milliways

1
@Milliways Bạn nói đúng, "tập lệnh hệ thống" dù sao cũng là một cách viết sai nên tôi đã thay đổi tiêu đề. Tôi không đồng ý về điều foobar - mọi người cần học cách nhận ra các biệt ngữ / thông tục phổ biến giống như trong bất kỳ nền văn hóa nào. Ngoài ra nó vẫn là một tiếng cười khúc khích tốt khi bạn đặt hai người lại với nhau.
goldilocks

Câu trả lời:


8

Đầu tiên, nếu tập lệnh được chạy bởi trình nền hệ thống và trình nền đó đang chạy với quyền root, bạn không cần sử dụng sudo. Điều này bao gồm init(và systemd), bao gồm rc.local. Nếu daemon đó không chạy với quyền root, thì nó sudosẽ không hoạt động trừ khi /etc/sudoersđược cấu hình để cho phép như vậy (và không có mật khẩu). Người dùng Raspbian có thể bị nhầm lẫn bởi điều này vì pingười dùng được phép làm bất cứ điều gì theo mặc định (và nếu bạn nhìn vào, /etc/sudoersbạn sẽ thấy điều đó được thực hiện như thế nào).

Tiếp theo, bạn có thể nắm bắt đầu ra từ bất kỳ bashtập lệnh nào hoặc bất kỳ nhóm lệnh nào bên trong tập lệnh bash, bằng cách thực hiện chúng trong một khung con như thế này: 1

(
    /bin/foo on 3
    sudo bar a
) &> /var/log/myTestLog.txt

Các ()chỉ ra một subshell . Tất cả đầu ra từ bất cứ thứ gì bên trong này đang được chuyển hướng đến một /var/log/myTestLog.txttệp. Một vài lưu ý:

  • &>là một bashism , vì vậy nếu tập lệnh được thực thi thông qua một shebang trên dòng đầu tiên, thì nó sẽ #!/bin/bashkhông, không chỉ /bin/sh. "Bashism" chỉ hoạt động trong bashvỏ.

    Điều này bao gồm /etc/rc.local, theo mặc định sử dụng /bin/sh(nghĩa là, vâng, bạn có thể thay đổi điều đó thành an toàn /bin/bash).

  • /var/logyêu cầu quyền root để ghi vào. Nếu quy trình không có như vậy, hãy sử dụng hoặc tạo một thư mục mà bạn biết nó có thể. Khi nghi ngờ, nếu bạn có thể kiểm tra điều này mà không phải tắt hoặc khởi động lại hệ thống, hãy sử dụng /tmp, có thể ghi được trên thế giới (tức là bởi bất kỳ ai). Tuy nhiên /tmpkhông tồn tại trên giày. Nó cũng là một phân vùng nhỏ, dựa trên RAM, vì vậy đừng ghi các hợp đồng dữ liệu vào nó. Đó không phải là thẻ SD của bạn [thực tế là trên các phiên bản hiện tại của Raspbian, nhưng đừng tin vào điều này trong thực tế] .

  • &>sẽ ghi đè lên bất cứ điều gì trong myTestLog.txt. Nếu thay vào đó, bạn muốn nối vào nhật ký hiện có, đó có thể là một ý tưởng tốt cho mục đích gỡ lỗi, hãy sử dụng &>>. Sau đó, bạn có thể thêm một lệnh vào đầu của lớp con như thế này:

    echo Starting $(date)

    Để tách thông tin từ mỗi lần chạy. Nếu bạn không chắc chắn điều này sẽ làm gì, hãy thử trên dòng lệnh.

Điểm cuối cùng này là một minh họa tốt về một cái gì đó bạn có thể làm liên quan đến các lệnh không xuất ra bất cứ thứ gì - nhưng hầu hết chúng sẽ làm nếu bạn bao gồm, ví dụ, -vcho "verbose". Coi chừng một số lệnh -vcó nghĩa là "thông tin phiên bản in". Có một cái nhìn trong trang man cho lệnh để chắc chắn nếu và cách thức hoạt động của nó (một số lệnh cũng sử dụng một công tắc khác so với -v).

Theo quy ước, các lệnh cũng trả về giá trị 0 khi hoàn thành. Điều này đôi khi được gọi là "trạng thái thoát" và bạn thường không thấy nó, nhưng trình bao sẽ hiển thị cho bạn echo $?. Thử

 ls /
 echo $?
 ls /nonexistantdir
 echo $?

Bạn sẽ nhận được 0 và 2. Nếu sau đó bạn tìm trong trang hướng lsdẫn trong phần "Thoát trạng thái", bạn sẽ thấy khá khó hiểu, khó hiểu:

2      if serious trouble (e.g., cannot access command-line argument).

Mà có thể hoặc không thể tốt hơn không có gì, nhưng có bạn đi.

Ít nhất, điều này cho thấy lệnh thất bại vì một số lý do. Trạng thái thoát cũng cho phép bạn làm những việc như thế này:

/bin/foo && sudo bar

Trong &&trường hợp này có nghĩa là "nếu lệnh đầu tiên thành công", giả sử lệnh đầu tiên sử dụng quy ước trả về 0 (đó là lý do tại sao họ thường làm). Nếu /bin/fookhông hoạt động, không thể được tìm thấy, vv, thì sudo barsẽ không bao giờ xảy ra.

Sử dụng kết hợp các thông điệp ghi nhật ký và thực thi có điều kiện ( &&) sẽ giúp bạn tiến gần hơn đến việc tìm ra vấn đề hoặc ít nhất là nhận thông tin có thể hữu ích cho người khác trong việc giúp bạn giải quyết vấn đề. Không có điều đó, hầu hết những người khác thường có thể làm là đoán.


1. Bạn có thể thực hiện cùng một chuyển hướng đầu ra cho toàn bộ tập lệnh từ bên trong bằng cách sử dụng:

exec &> /var/log/myTestLog.txt

Ở trên cùng (hoặc bất cứ nơi nào, và nó sẽ áp dụng cho mọi thứ tiếp theo).


2

Một khía cạnh quan trọng mọi người có xu hướng quên khi chạy các kịch bản như daemon là môi trường shell và $PATHđặc biệt là biến. Trong ví dụ của bạn, dòng thứ hai dựa vào $PATH: tên đầy đủ sudo/usr/bin/sudovà vỏ người dùng của bạn chỉ biết rằng vì nó được yêu cầu tìm kiếm /usr/binkhi tìm kiếm các tệp thực thi. Điều này cũng đúng với bar.

Xem xét rằng sudokhông cần thiết khi chạy tập lệnh dưới dạng trình nền, dòng thứ hai của bạn sẽ giống như:

/path/to/bar a
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.