在网上搜索解决方案但没有找到库后,我尝试使用 csharp 编写一个 systemd 日志阅读器,但运气不佳。
以下链接底部有一个用 C++ 编写的示例:
https://www.freedesktop.org/software/systemd/man/latest/sd_journal_next.html
<<< SEE UPDATE BELOW >>>
这是我到目前为止的代码,当我运行它时,我得到了
$ ./LogPublisher
errno: 0
errno: -10
errno: -10
errno: -10 Message:
据我所知,
-10
指的是No child processes
,取自https://en.wikipedia.org/wiki/Errno.h
using System.Runtime.InteropServices;
using System.Text;
class Program
{
enum Flags
{
SD_JOURNAL_LOCAL_ONLY = 1 << 0, // 0000 0001 = 1
SD_JOURNAL_RUNTIME_ONLY = 1 << 1, // 0000 0010 = 2
SD_JOURNAL_SYSTEM = 1 << 2, // 0000 0100 = 4
SD_JOURNAL_CURRENT_USER = 1 << 3, // 0000 1000 = 8
SD_JOURNAL_OS_ROOT = 1 << 4, // 0001 0000 = 16
SD_JOURNAL_ALL_NAMESPACES = 1 << 5, // (32) Show all namespaces, not just the default or specified one */
SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE = 1 << 6, // (64) Show default namespace in addition to specified one */
SD_JOURNAL_TAKE_DIRECTORY_FD = 1 << 7, // (128) sd_journal_open_directory_fd() will take ownership of the provided file descriptor. */
SD_JOURNAL_ASSUME_IMMUTABLE = 1 << 8, // (256) Assume the opened journal files are immutable. Journal entries added later may be ignored. */
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct Journal
{
public int toplevel_fd; // int toplevel_fd;
public string path; // char *path;
public string prefix; // char *prefix;
public string _namespace; // char *namespace;
public UIntPtr files; // OrderedHashmap *files;
public UIntPtr files_cache; // IteratedCache *files_cache;
public UIntPtr mmap; // MMapCache *mmap;
public UIntPtr newest_by_boot_id; // NewestByBootId *newest_by_boot_id;
public ulong n_newest_by_boot_id; // size_t n_newest_by_boot_id;
public UIntPtr current_location; // Location current_location;
public UIntPtr current_file; // JournalFile *current_file;
public ulong current_field; // uint64_t current_field;
public UIntPtr level0; // Match *level0;
public UIntPtr level1; // Match *level1;
public UIntPtr level2; // Match *level2;
public UIntPtr exclude_syslog_identifiers; // Set *exclude_syslog_identifiers;
public ulong origin_id; // uint64_t origin_id;
public int inotify_fd; // int inotify_fd;
public uint current_invalidate_counter; // unsigned current_invalidate_counter
public uint last_invalidate_counter; // unsigned last_invalidate_counter
public ulong last_process_usec; // usec_t last_process_usec;
public uint generation; // unsigned generation;
public string unique_field; // char *unique_field;
public UIntPtr unique_file; // JournalFile *unique_file;
public ulong unique_offset; // uint64_t unique_offset;
public UIntPtr fields_file; // JournalFile *fields_file;
public ulong fields_offset; // uint64_t fields_offset;
public ulong fields_hash_table_index; // uint64_t fields_hash_table_index;
public string fields_buffer; // char *fields_buffer;
public int flags; // int flags;
public bool on_network = true; // bool on_network:1;
public bool no_new_files = true; // bool no_new_files:1;
public bool no_inotify = true; // bool no_inotify:1;
public bool unique_file_lost = true; // bool unique_file_lost:1;
public bool fields_file_lost = true; // bool fields_file_lost:1;
public bool has_runtime_files = true; // bool has_runtime_files:1;
public bool has_persistent_files = true; // bool has_persistent_files:1;
public ulong data_threshold; // size_t data_threshold;
public UIntPtr directories_by_path; // Hashmap *directories_by_path;
public UIntPtr directories_by_wd; // Hashmap *directories_by_wd;
public UIntPtr errors; // Hashmap *errors;
public Journal() { }
}
internal static class Systemd
{
[DllImport("libsystemd.so.0", CharSet = CharSet.Ansi)]
internal static extern int sd_journal_open(ref Journal sd_journal, int flags);
[DllImport("libsystemd.so.0", CharSet = CharSet.Ansi)]
internal static extern void sd_journal_close(ref Journal sd_journal);
[DllImport("libsystemd.so.0", CharSet = CharSet.Ansi)]
internal static extern int sd_journal_seek_head(ref Journal sd_journal);
[DllImport("libsystemd.so.0", CharSet = CharSet.Ansi)]
internal static extern int sd_journal_seek_tail(ref Journal sd_journal);
[DllImport("libsystemd.so.0", CharSet = CharSet.Ansi)]
internal static extern int sd_journal_next(ref Journal sd_journal);
[DllImport("libsystemd.so.0", CharSet = CharSet.Ansi)]
internal static extern int sd_journal_previous(ref Journal sd_journal);
[DllImport("libsystemd.so.0", CharSet = CharSet.Ansi)]
internal static extern int sd_journal_get_data(ref Journal sd_journal, string field, [Out] StringBuilder data, [Out] ulong length);
}
static void Main()
{
int errno;
Journal j = new();
errno = Systemd.sd_journal_open(ref j, (int)Flags.SD_JOURNAL_LOCAL_ONLY);
Console.WriteLine($"errno: {errno}");
Console.WriteLine($"path: {j.path}");
errno = Systemd.sd_journal_seek_head(ref j);
Console.WriteLine($"errno: {errno}");
errno = Systemd.sd_journal_next(ref j);
Console.WriteLine($"errno: {errno}");
ulong length = 0;
StringBuilder data = new(1024 * 768 * 4);
errno = Systemd.sd_journal_get_data(ref j, "MESSAGE", data, length);
Console.WriteLine($"errno: {errno} Message: {data}");
Systemd.sd_journal_close(ref j);
}
}
我一直在尝试参考日志的源代码来复制,但就是无法解决。
https://github.com/systemd/systemd/blob/main/src/systemd/sd-journal.h
参考上面的代码,为什么我会收到该错误? 我的代码是否走在正确的轨道上,还是偏离了正轨?我是否使用
ref Journal j
正确引用了《华尔街日报》?有没有人写过类似的东西并可以分享他们的代码?
更新
在评论中的感谢下,已经取得了进展。 现在的输出给了我
$ ./LogPublisher
result: 0
result: 0
result: 1
result: -22 Message: 0 Length: 0
使用以下代码
using System.Runtime.InteropServices;
using System.Text;
class Program
{
enum Flags
{
SD_JOURNAL_LOCAL_ONLY = 1 << 0, // 0000 0001 = 1
SD_JOURNAL_RUNTIME_ONLY = 1 << 1, // 0000 0010 = 2
SD_JOURNAL_SYSTEM = 1 << 2, // 0000 0100 = 4
SD_JOURNAL_CURRENT_USER = 1 << 3, // 0000 1000 = 8
SD_JOURNAL_OS_ROOT = 1 << 4, // 0001 0000 = 16
SD_JOURNAL_ALL_NAMESPACES = 1 << 5, // (32) Show all namespaces, not just the default or specified one */
SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE = 1 << 6, // (64) Show default namespace in addition to specified one */
SD_JOURNAL_TAKE_DIRECTORY_FD = 1 << 7, // (128) sd_journal_open_directory_fd() will take ownership of the provided file descriptor. */
SD_JOURNAL_ASSUME_IMMUTABLE = 1 << 8, // (256) Assume the opened journal files are immutable. Journal entries added later may be ignored. */
}
static class Systemd
{
[DllImport("libsystemd.so.0", CharSet = CharSet.Ansi)]
internal static extern int sd_journal_open(ref UIntPtr sd_journal, int flags);
[DllImport("libsystemd.so.0", CharSet = CharSet.Ansi)]
internal static extern void sd_journal_close(UIntPtr sd_journal);
[DllImport("libsystemd.so.0", CharSet = CharSet.Ansi)]
internal static extern int sd_journal_seek_head(UIntPtr sd_journal);
[DllImport("libsystemd.so.0", CharSet = CharSet.Ansi)]
internal static extern int sd_journal_seek_tail(UIntPtr sd_journal);
[DllImport("libsystemd.so.0", CharSet = CharSet.Ansi)]
internal static extern int sd_journal_step_one(UIntPtr sd_journal, int advanced);
[DllImport("libsystemd.so.0", CharSet = CharSet.Ansi)]
internal static extern int sd_journal_next(UIntPtr sd_journal);
[DllImport("libsystemd.so.0", CharSet = CharSet.Ansi)]
internal static extern int sd_journal_previous(UIntPtr sd_journal);
[DllImport("libsystemd.so.0", CharSet = CharSet.Ansi)]
internal static extern int sd_journal_get_data(UIntPtr sd_journal, string field, UIntPtr data, out ulong length);
}
static void Main()
{
int result; // negative number on error
UIntPtr j = new();
result = Systemd.sd_journal_open(ref j, (int)Flags.SD_JOURNAL_LOCAL_ONLY);
Console.WriteLine($"result: {result}"); // return 0 on success
result = Systemd.sd_journal_seek_head(j);
Console.WriteLine($"result: {result}"); // return 0 on success
result = Systemd.sd_journal_step_one(j, 0);
Console.WriteLine($"result: {result}"); // return the number of entries advanced/set back on success
UIntPtr data = new();
result = Systemd.sd_journal_get_data(j, "MESSAGE", data, out ulong length);
Console.WriteLine($"result: {result} Message: {data} Length: {length}");
Systemd.sd_journal_close(j);
}
}
还没有完全实现,因为我没有从 get_data 得到结果...
using System.Runtime.InteropServices;
class Program
{
enum Flags
{
SD_JOURNAL_LOCAL_ONLY = 1 << 0, // 0000 0001 = 1
SD_JOURNAL_RUNTIME_ONLY = 1 << 1, // 0000 0010 = 2
SD_JOURNAL_SYSTEM = 1 << 2, // 0000 0100 = 4
SD_JOURNAL_CURRENT_USER = 1 << 3, // 0000 1000 = 8
SD_JOURNAL_OS_ROOT = 1 << 4, // 0001 0000 = 16
SD_JOURNAL_ALL_NAMESPACES = 1 << 5, // (32) Show all namespaces, not just the default or specified one */
SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE = 1 << 6, // (64) Show default namespace in addition to specified one */
SD_JOURNAL_TAKE_DIRECTORY_FD = 1 << 7, // (128) sd_journal_open_directory_fd() will take ownership of the provided file descriptor. */
SD_JOURNAL_ASSUME_IMMUTABLE = 1 << 8, // (256) Assume the opened journal files are immutable. Journal entries added later may be ignored. */
}
static class Systemd
{
[DllImport("libsystemd.so.0", CharSet = CharSet.Ansi)]
internal static extern int sd_journal_open(ref UIntPtr sd_journal, int flags);
// int sd_journal_open(sd_journal **ret, int flags);
[DllImport("libsystemd.so.0", CharSet = CharSet.Ansi)]
internal static extern void sd_journal_close(UIntPtr sd_journal);
// void sd_journal_close(sd_journal *j);
[DllImport("libsystemd.so.0", CharSet = CharSet.Ansi)]
internal static extern int sd_journal_seek_head(UIntPtr sd_journal);
// int sd_journal_seek_head(sd_journal *j);
[DllImport("libsystemd.so.0", CharSet = CharSet.Ansi)]
internal static extern int sd_journal_seek_tail(UIntPtr sd_journal);
// int sd_journal_seek_tail(sd_journal *j);
[DllImport("libsystemd.so.0", CharSet = CharSet.Ansi)]
internal static extern int sd_journal_step_one(UIntPtr sd_journal, int advanced);
// int sd_journal_step_one(sd_journal *j, int advanced);
[DllImport("libsystemd.so.0", CharSet = CharSet.Ansi)]
internal static extern int sd_journal_next(UIntPtr sd_journal);
// int sd_journal_next(sd_journal *j);
[DllImport("libsystemd.so.0", CharSet = CharSet.Ansi)]
internal static extern int sd_journal_previous(UIntPtr sd_journal);
// int sd_journal_previous(sd_journal *j);
[DllImport("libsystemd.so.0", CharSet = CharSet.Ansi)]
internal static extern int sd_journal_get_data(UIntPtr sd_journal, string field, ref IntPtr data, ref ulong length);
// int sd_journal_get_data(sd_journal *j, const char *field, const void **data, size_t *l);
}
static void Main()
{
int result; // negative number on error
UIntPtr j = new();
result = Systemd.sd_journal_open(ref j, 0);
Console.WriteLine($"result: {result}"); // return 0 on success
result = Systemd.sd_journal_seek_head(j);
Console.WriteLine($"result: {result}"); // return 0 on success
ulong length;
IntPtr data;
while (true) {
result = Systemd.sd_journal_step_one(j, 1);
Console.WriteLine($"result: {result}"); // return the number of entries advanced/set back on success
if (result < 1) break;
data = new();
length = 0;
result = Systemd.sd_journal_get_data(j, "MESSAGE", ref data, ref length);
Console.WriteLine($"result: {result} Message: {Marshal.PtrToStringAuto(data)} Length: {length}");
}
Systemd.sd_journal_close(j);
}
}