Apakah ada cara untuk membuat jurnal menunjukkan log dari "layanan foo.ser terakhir kali"?

15

Saya sangat tertarik dengan ini untuk melihat output dari layanan oneshot yang berjalan pada timer. The --unitflag dekat, tapi merangkai semua berjalan layanan bersama-sama. Cara paling jelas yang dapat saya pikirkan adalah menyaring PID, tetapi itu membuat saya khawatir tentang penggunaan kembali PID / layanan yang bercabang, dan mendapatkan PID terakhir cukup merepotkan. Apakah ada pengenal lain yang sesuai dengan satu kali menjalankan layanan, yang bisa saya gunakan untuk menyaring log?

EDIT: Saya akan dengan senang hati menerima "tidak" yang otoritatif jika itu jawaban yang sebenarnya.

Jack O'Connor
sumber

Jawaban:

6

Sejak systemdversi 232, kami memiliki konsep ID doa. Setiap kali unit dijalankan, ia memiliki ID doa 128 bit yang unik. Tidak seperti MainPIDyang dapat didaur ulang, atau ActiveEnterTimestampyang dapat memiliki masalah resolusi, itu adalah cara yang gagal untuk mendapatkan semua log dari permintaan unit systemd tertentu.

Untuk mendapatkan ID doa terbaru dari suatu unit

$ systemctl show --value -p InvocationID openipmi
bd3eb84c3aa74169a3dcad2af183885b

Untuk mendapatkan jurnal permohonan terbaru, katakanlah openipmi, apakah itu gagal atau tidak, Anda dapat menggunakan liner satu

$ journalctl _SYSTEMD_INVOCATION_ID=`systemctl show -p InvocationID --value openipmi.service`
-- Logs begin at Thu 2018-07-26 12:09:57 IDT, end at Mon 2019-07-08 01:32:50 IDT. --
Jun 21 13:03:13 build03.lbits openipmi[1552]:  * Starting ipmi drivers
Jun 21 13:03:13 build03.lbits openipmi[1552]:    ...fail!
Jun 21 13:03:13 build03.lbits openipmi[1552]:    ...done.

(Perhatikan bahwa --valuetersedia sejak systemd 230, lebih tua dari InvocationID)

Elazar Leibovich
sumber
Jika seseorang mencoba untuk menyelidiki ini: journalctl --user -u UNITFILE -f -o json-prettymungkin bisa membantu; Anda sedang mencari MESSAGEbidang khususnya. Saya menemukan bahwa Anda mungkin juga perlu USER_INVOCATION_ID, dan juga beberapa pesan tidak memiliki id doa yang menyertainya, jadi tidak dapat difilter melalui mekanisme ini. Tidak yakin mengapa, mungkin penebangan saya salah konfigurasi ..
karlicoss
14

Saya tidak yakin cap waktu mana yang paling masuk akal tetapi ini bekerja untuk saya. Mudah-mudahan ada cara yang lebih baik untuk bekerja dengan stempel waktu dari systemctl showawk - tidak bisa mengetahui cara mengontrol format stempel waktu.

unit=foo.service

ts=$(systemctl show -p ActiveEnterTimestamp $unit)

echo $ts
ActiveEnterTimestamp=Fri 2016-11-11 12:30:01 MST

journalctl -u $unit --since "$(echo $ts | awk '{print $2 $3}')"
Erik Stephens
sumber
Untuk berjaga-jaga jika seseorang membutuhkannya sebagai satu-liner: journalctl --since " systemctl show -p ActiveEnterTimestamp thermo.service | awk '{print $2 \" \" $3}'" -fu thermo.service | kurang
DimanNe
Anda juga dapat menggunakan systemctl show -p ActiveEnterTimestamp --value $unit, jadi tidak perlu awk tambahan
karlicoss
4

Anda dapat menggunakan flag boot untuk mengambil hanya log dari boot itu. contohnya

journalctl _SYSTEMD_UNIT=avahi-daemon.service -b 5
Nikolaidis Fotis
sumber
2
Ini mirip dengan yang saya inginkan, tetapi tidak berfungsi dalam situasi seperti: 1) jika mesin telah reboot sejak terakhir kali layanan berjalan, atau 2) jika layanan telah berjalan beberapa kali sejak boot terakhir.
Jack O'Connor
Saya tidak yakin mengapa itu tidak berhasil untuk kasus ke-1. Jika sudah di-reboot, akan di-reboot juga. Anda hanya perlu pergi ke boot spesifik itu dan mengambil info Anda. Mengenai yang kedua ... Anda benar. Log kebisingan tergantung pada berapa kali layanan telah di-reboot. Tetapi begitu Anda telah melihat pid layanan Anda, Anda dapat memfilternya menggunakan _PID = XXX argumen. Peluang menggunakan kembali pid yang sama untuk layanan yang sama pada siklus boot yang sama adalah ..... tidak tahu ... tapi hampir tidak mungkin.
Nikolaidis Fotis
Saya tertarik menangani layanan yang tidak selalu berjalan saat boot, baik karena mereka menggunakan timer atau karena itu perintah satu kali.
Jack O'Connor
3

Ini mungkin membantu Anda:

  • jurnalctl -u foo.service | ekor -n 2

    atau ganti 2 dengan jumlah garis yang diharapkan

  • jurnalctl -u foo.service --since = ' 2016-04-11 13:00:00 '

Anda juga dapat menggabungkannya untuk mendapatkan cap waktu waktu jalankan terakhir, dan kemudian menggunakan stempel waktu itu dengan --since switch.

Breign
sumber
Ini terasa seperti solusi yang mirip dengan pendekatan PID, tetapi ini sangat manual. Jika layanan saya berjalan lebih dari beberapa detik, dan mengeluarkan banyak baris log, saya harus mencari baris pertama yang memiliki stempel waktu mulai yang saya pedulikan. Itu tidak akan bekerja dengan baik dalam sebuah skrip.
Jack O'Connor
3

Anda dapat menggunakan filter bidang dengan Journalctl. Misalnya

journalctl _PID=1234

Dapatkan daftar semua bidang yang tersedia menggunakan:

journalctl --fields --unit kubelet

Satu bidang yang tersedia adalah _PID.

Anda bisa mendapatkan PID dari proses yang berjalan menggunakan pidofatausystemctl show --property MainPID <SERVICE_NAME>

Jadi, inilah cara saya mendapatkan log dari proses kubelet Kubernet saat ini:

# journalctl --unit kubelet _PID=$(systemctl show --property MainPID kubelet 2>/dev/null | cut -d= -f2) | head

Sekarang beritahu saya mengapa saya Kubernetes sangat sulit untuk menginstal :-(

richardw
sumber
0

jurnalctl -r | grep -m1 foo.service

nieman
sumber
Selamat datang di ServerFault. Bisakah Anda menjelaskan bagaimana ini lebih baik atau berbeda dari jawaban lain yang sudah ada di sini? serverfault.com/help/how-to-answer
chicks