1 use std
::process
::{Command, Stdio}
;
4 use serde_json
::{json, Value}
;
6 use proxmox
::api
::{api, ApiMethod, Router, RpcEnvironment, Permission}
;
8 use pbs_api_types
::{NODE_SCHEMA, SYSTEMD_DATETIME_FORMAT, PRIV_SYS_AUDIT}
;
15 service
: Option
<&str>,
16 ) -> Result
<(u64, Vec
<Value
>), Error
> {
18 let mut args
= vec
!["-o", "short", "--no-pager"];
20 if let Some(service
) = service { args.extend(&["--unit", service]); }
21 if let Some(since
) = since { args.extend(&["--since", since]); }
22 if let Some(until
) = until { args.extend(&["--until", until]); }
24 let mut lines
: Vec
<Value
> = vec
![];
25 let mut limit
= limit
.unwrap_or(50);
26 let start
= start
.unwrap_or(0);
27 let mut count
: u64 = 0;
29 let mut child
= Command
::new("journalctl")
31 .stdout(Stdio
::piped())
34 use std
::io
::{BufRead,BufReader}
;
36 if let Some(ref mut stdout
) = child
.stdout
{
37 for line
in BufReader
::new(stdout
).lines() {
41 if count
< start { continue }
;
42 if limit
== 0 { continue }
;
44 lines
.push(json
!({ "n": count, "t": line }
));
49 log
::error
!("reading journal failed: {}", err
);
57 let status
= child
.wait().unwrap();
58 if !status
.success() {
59 log
::error
!("journalctl failed with {}", status
);
62 // HACK: ExtJS store.guaranteeRange() does not like empty array
66 lines
.push(json
!({ "n": count, "t": "no content"}
));
81 description
: "Start line number.",
87 description
: "Max. number of lines.",
94 description
: "Display all log since this date-time string.",
95 format
: &SYSTEMD_DATETIME_FORMAT
,
100 description
: "Display all log until this date-time string.",
101 format
: &SYSTEMD_DATETIME_FORMAT
,
106 description
: "Service ID.",
113 description
: "Returns a list of syslog entries.",
117 description
: "Line number.",
121 description
: "Line text.",
126 permission
: &Permission
::Privilege(&["system", "log"], PRIV_SYS_AUDIT
, false),
129 /// Read syslog entries.
133 mut rpcenv
: &mut dyn RpcEnvironment
,
134 ) -> Result
<Value
, Error
> {
136 let service
= if let Some(service
) = param
["service"].as_str() {
137 Some(crate::api2
::node
::services
::real_service_name(service
))
142 let (count
, lines
) = dump_journal(
143 param
["start"].as_u64(),
144 param
["limit"].as_u64(),
145 param
["since"].as_str(),
146 param
["until"].as_str(),
149 rpcenv
["total"] = Value
::from(count
);
154 pub const ROUTER
: Router
= Router
::new()
155 .get(&API_METHOD_GET_SYSLOG
);