'\" t .TH "ORG\&.FREEDESKTOP\&.LOGCONTROL1" "5" "" "systemd 261.2" "org.freedesktop.LogControl1" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "نام (NAME)" org.freedesktop.LogControl1 \- رابط دی‌باس برای کنترل ثبت رویدادها در سرویس‌های سیستم‌دی .SH "مقدمه (INTRODUCTION)" .PP org\&.freedesktop\&.LogControl1 یک رابط عمومی است که برای استفاده توسط هر دیمنی در نظر گرفته شده که امکان پرس‌وجو و تنظیم سطح و مقصد ثبت رویداد (لاگ‌گیری) را از طریق D\-Bus فراهم می‌کند\&. این رابط توسط دیمن‌های گوناگونی که بخشی از مجموعه \fBsystemd\fR(1) هستند پیاده‌سازی شده است\&. .PP فرض بر این است که این تنظیمات برای کل برنامه به‌صورت سراسری هستند، بنابراین از یک مسیر شیء ثابت استفاده می‌شود\&. این رابط باید همیشه در مسیر /org/freedesktop/LogControl1 در دسترس باشد\&. .SH "توضیحات (DESCRIPTION)" .PP رابط زیر ارائه شده است: .sp .if n \{\ .RS 4 .\} .nf node /org/freedesktop/LogControl1 { interface org\&.freedesktop\&.LogControl1 { properties: @org\&.freedesktop\&.DBus\&.Property\&.EmitsChangedSignal("false") @org\&.freedesktop\&.systemd1\&.Privileged("true") readwrite s LogLevel = \*(Aq\&.\&.\&.\*(Aq; @org\&.freedesktop\&.DBus\&.Property\&.EmitsChangedSignal("false") @org\&.freedesktop\&.systemd1\&.Privileged("true") readwrite s LogTarget = \*(Aq\&.\&.\&.\*(Aq; @org\&.freedesktop\&.DBus\&.Property\&.EmitsChangedSignal("false") readonly s SyslogIdentifier = \*(Aq\&.\&.\&.\*(Aq; }; interface org\&.freedesktop\&.DBus\&.Peer { \&.\&.\&. }; interface org\&.freedesktop\&.DBus\&.Introspectable { \&.\&.\&. }; interface org\&.freedesktop\&.DBus\&.Properties { \&.\&.\&. }; }; .fi .if n \{\ .RE .\} .SS "ویژگی‌ها (Properties)" .PP ویژگی \fILogLevel\fR سطح لاگ‌گیری به سبک \fBsyslog\fR(3) را توصیف می‌کند، و باید یکی از مقادیر "emerg", "alert", "crit", "err", "warning", "notice", "info", "debug" به ترتیب افزایش میزان جزئیات باشد\&. .PP ویژگی \fILogTarget\fR مقصد (سازوکار) لاگ‌گیری را توصیف می‌کند\&. این ویژگی باید یکی از موارد زیر باشد: "console" (ثبت لاگ در کنسول یا خروجی استاندارد)، "kmsg" (ثبت لاگ در بافر حلقه‌ای هسته)، "journal" (ثبت لاگ به‌طور مستقیم در ژورنال، ببینید: \fBsystemd-journald.service\fR(8))، "syslog" (ثبت لاگ با استفاده از فراخوانی \fBsyslog\fR(3))\&. .if n \{\ .sp .\} .RS 4 .it 1 an-trap .nr an-no-space-flag 1 .nr an-break-flag 1 .br .ps +1 \fBدسترسی نوشتن (Write Access)\fR .ps -1 .br .PP ویژگی‌های \fILogLevel\fR و \fILogTarget\fR باید قابل نوشتن باشند\&. باید دقت شود تا اطمینان حاصل گردد تنها کلاینت‌هایی با دسترسی و امتیاز مناسب می‌توانند آن‌ها را تغییر دهند\&. .sp .5v .RE .PP ویژگی \fISyslogIdentifier\fR یک ویژگی فقط‌خواندنی است که «شناسه syslog» را نشان می‌دهد\&. این یک رشته کوتاه است که برنامه مبدأ پیام‌های لاگ ارسالی به فراخوانی \fBsyslog\fR(3) را مشخص می‌کند\&. .SH "ابزارها (TOOLS)" .PP گزینه \fB\-p\fR/\fB\-\-priority=\fR در \fBjournalctl\fR می‌تواند برای فیلتر کردن پیام‌های لاگ بر اساس سطح لاگ استفاده شود، گزینه \fB\-t\fR/\fB\-\-identifier=\fR می‌تواند بر اساس شناسه syslog به کار رود، و فیلترهایی مانند "_TRANSPORT=syslog", "_TRANSPORT=journal", و "_TRANSPORT=kernel" می‌توانند برای فیلتر کردن پیام‌ها بر اساس سازوکاری که از طریق آن به \fBsystemd\-journald\fR رسیده‌اند استفاده شوند\&. .PP دستورهای فرعی \fBsystemctl log\-level\fR و \fBsystemctl log\-target\fR می‌توانند برای پرس‌وجو و تنظیم ویژگی‌های \fILogLevel\fR و \fILogTarget\fR مدیر سرویس به کار روند\&. همچنین \fBsystemctl service\-log\-level\fR و \fBsystemctl service\-log\-target\fR می‌توانند به طور مشابه برای سرویس‌های منفرد استفاده شوند\&. (سرویس‌ها باید ویژگی \fIBusName=\fR را تنظیم کرده باشند و رابط شرح داده شده در اینجا را پیاده‌سازی کنند\&. برای جزئیات درباره \fIBusName=\fR صفحه راهنمای \fBsystemd.service\fR(5) را ببینید\&.) .SH "مثال‌ها (EXAMPLES)" .PP \fBمثال\ \&۱.\ \&ایجاد یک شنونده ساده روی گذرگاه که LogControl1 را پیاده‌سازی می‌کند\fR .sp .if n \{\ .RS 4 .\} .nf /* SPDX\-License\-Identifier: MIT\-0 */ /* Implements the LogControl1 interface as per specification: * https://www\&.freedesktop\&.org/software/systemd/man/org\&.freedesktop\&.LogControl1\&.html * * Compile with \*(Aqcc logcontrol\-example\&.c $(pkg\-config \-\-libs \-\-cflags libsystemd)\*(Aq * * To get and set properties via busctl: * * $ busctl \-\-user get\-property org\&.freedesktop\&.Example \e * /org/freedesktop/LogControl1 \e * org\&.freedesktop\&.LogControl1 \e * SyslogIdentifier * s "example" * $ busctl \-\-user get\-property org\&.freedesktop\&.Example \e * /org/freedesktop/LogControl1 \e * org\&.freedesktop\&.LogControl1 \e * LogTarget * s "journal" * $ busctl \-\-user get\-property org\&.freedesktop\&.Example \e * /org/freedesktop/LogControl1 \e * org\&.freedesktop\&.LogControl1 \e * LogLevel * s "info" * $ busctl \-\-user set\-property org\&.freedesktop\&.Example \e * /org/freedesktop/LogControl1 \e * org\&.freedesktop\&.LogControl1 \e * LogLevel \e * "s" debug * $ busctl \-\-user get\-property org\&.freedesktop\&.Example \e * /org/freedesktop/LogControl1 \e * org\&.freedesktop\&.LogControl1 \e * LogLevel * s "debug" */ #include #include #include #include #include #include #define _cleanup_(f) __attribute__((cleanup(f))) static int log_error(int log_level, int error, const char *str) { sd_journal_print(log_level, "%s failed: %s", str, strerror(\-error)); return error; } typedef enum LogTarget { LOG_TARGET_JOURNAL, LOG_TARGET_KMSG, LOG_TARGET_SYSLOG, LOG_TARGET_CONSOLE, _LOG_TARGET_MAX, } LogTarget; static const char* const log_target_table[_LOG_TARGET_MAX] = { [LOG_TARGET_JOURNAL] = "journal", [LOG_TARGET_KMSG] = "kmsg", [LOG_TARGET_SYSLOG] = "syslog", [LOG_TARGET_CONSOLE] = "console", }; static const char* const log_level_table[LOG_DEBUG + 1] = { [LOG_EMERG] = "emerg", [LOG_ALERT] = "alert", [LOG_CRIT] = "crit", [LOG_ERR] = "err", [LOG_WARNING] = "warning", [LOG_NOTICE] = "notice", [LOG_INFO] = "info", [LOG_DEBUG] = "debug", }; typedef struct object { const char *syslog_identifier; LogTarget log_target; int log_level; } object; static int property_get( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { object *o = userdata; if (strcmp(property, "LogLevel") == 0) return sd_bus_message_append(reply, "s", log_level_table[o\->log_level]); if (strcmp(property, "LogTarget") == 0) return sd_bus_message_append(reply, "s", log_target_table[o\->log_target]); if (strcmp(property, "SyslogIdentifier") == 0) return sd_bus_message_append(reply, "s", o\->syslog_identifier); return sd_bus_error_setf(error, SD_BUS_ERROR_UNKNOWN_PROPERTY, "Unknown property \*(Aq%s\*(Aq", property); } static int property_set( sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *message, void *userdata, sd_bus_error *error) { object *o = userdata; const char *value; int r; r = sd_bus_message_read(message, "s", &value); if (r < 0) return r; if (strcmp(property, "LogLevel") == 0) { int i; for (i = 0; i < LOG_DEBUG + 1; i++) if (strcmp(value, log_level_table[i]) == 0) { o\->log_level = i; setlogmask(LOG_UPTO(i)); return 0; } return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid value for LogLevel: \*(Aq%s\*(Aq", value); } if (strcmp(property, "LogTarget") == 0) { LogTarget i; for (i = 0; i < _LOG_TARGET_MAX; i++) if (strcmp(value, log_target_table[i]) == 0) { o\->log_target = i; return 0; } return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid value for LogTarget: \*(Aq%s\*(Aq", value); } return sd_bus_error_setf(error, SD_BUS_ERROR_UNKNOWN_PROPERTY, "Unknown property \*(Aq%s\*(Aq", property); } /* https://www\&.freedesktop\&.org/software/systemd/man/sd_bus_add_object\&.html */ static const sd_bus_vtable vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_WRITABLE_PROPERTY( "LogLevel", "s", property_get, property_set, 0, 0), SD_BUS_WRITABLE_PROPERTY( "LogTarget", "s", property_get, property_set, 0, 0), SD_BUS_PROPERTY( "SyslogIdentifier", "s", property_get, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_VTABLE_END }; int main(int argc, char **argv) { /* The bus should be relinquished before the program terminates\&. The cleanup * attribute allows us to do it nicely and cleanly whenever we exit the * block\&. */ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; object o = { \&.log_level = LOG_INFO, \&.log_target = LOG_TARGET_JOURNAL, \&.syslog_identifier = "example", }; int r; /* https://man7\&.org/linux/man\-pages/man3/setlogmask\&.3\&.html * Programs using syslog() instead of sd_journal can use this API to cut logs * emission at the source\&. */ setlogmask(LOG_UPTO(o\&.log_level)); /* Acquire a connection to the bus, letting the library work out the details\&. * https://www\&.freedesktop\&.org/software/systemd/man/sd_bus_default\&.html */ r = sd_bus_default(&bus); if (r < 0) return log_error(o\&.log_level, r, "sd_bus_default()"); /* Publish an interface on the bus, specifying our well\-known object access * path and public interface name\&. * https://www\&.freedesktop\&.org/software/systemd/man/sd_bus_add_object\&.html * https://dbus\&.freedesktop\&.org/doc/dbus\-tutorial\&.html */ r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/LogControl1", "org\&.freedesktop\&.LogControl1", vtable, &o); if (r < 0) return log_error(o\&.log_level, r, "sd_bus_add_object_vtable()"); /* By default, the service is assigned an ephemeral name\&. Also add a fixed * one, so that clients know whom to call\&. * https://www\&.freedesktop\&.org/software/systemd/man/sd_bus_request_name\&.html */ r = sd_bus_request_name(bus, "org\&.freedesktop\&.Example", 0); if (r < 0) return log_error(o\&.log_level, r, "sd_bus_request_name()"); for (;;) { /* https://www\&.freedesktop\&.org/software/systemd/man/sd_bus_wait\&.html */ r = sd_bus_wait(bus, UINT64_MAX); if (r < 0) return log_error(o\&.log_level, r, "sd_bus_wait()"); /* https://www\&.freedesktop\&.org/software/systemd/man/sd_bus_process\&.html */ r = sd_bus_process(bus, NULL); if (r < 0) return log_error(o\&.log_level, r, "sd_bus_process()"); } /* https://www\&.freedesktop\&.org/software/systemd/man/sd_bus_release_name\&.html */ r = sd_bus_release_name(bus, "org\&.freedesktop\&.Example"); if (r < 0) return log_error(o\&.log_level, r, "sd_bus_release_name()"); return 0; } .fi .if n \{\ .RE .\} .PP این کد یک سرور ساده روی گذرگاه ایجاد می‌کند\&. با ارائه ویژگی‌های مورد نیاز و اجازه دادن به تنظیم موارد قابل نوشتن، رابط LogControl1 را پیاده‌سازی می‌نماید\&. همچنین رویدادها را در سطح لاگ پیکربندی‌شده با استفاده از \fBsd_journal_print\fR(3) ثبت می‌کند\&. .PP توجه داشته باشید که هنگام پورت کردن این مثال به سایر کتابخانه‌های D\-Bus ممکن است افزودن بررسی‌های دستی امتیاز دسترسی کلاینت لازم باشد، زیرا آن‌ها معمولاً رفتارهای محدودکننده پیش‌فرض sd\-bus را ندارند؛ در sd\-bus دسترسی بدون امتیاز به ویژگی‌ها از طریق فلگ \fBSD_BUS_VTABLE_UNPRIVILEGED\fR کنترل می‌شود که اختیاری و انتخابی (opt\-in) است نه انصرافی (opt\-out)\&. .SH "همچنین ببینید (SEE ALSO)" .PP \fBsystemd\fR(1), \fBjournalctl\fR(1), \fBsystemctl\fR(1), \fBsystemd.service\fR(5), \fBsyslog\fR(3)