GuillaumeGomez / sysinfo

Cross-platform library to fetch system information
MIT License
2.02k stars 302 forks source link

Add FreeBSD support? #433

Closed mjarkk closed 2 years ago

mjarkk commented 3 years ago

As FreeBSD is still used on lots of places it might be nice to support it.
I don't think you want to add this but are you open to PRs to support FreeBSD?

GuillaumeGomez commented 3 years ago

I gave it a try a long time ago but had issues finding some information. If you feel like giving it a try, you're very welcome to do so!

mjarkk commented 3 years ago

Ah that's a bummer, i've always been interested in freebsd but never found any reason to use it so this might be a nice way to learn some new things.

GuillaumeGomez commented 3 years ago

Good luck then. :wink:

kraileth commented 3 years ago

A general hint to anybody who would like to give it a try: In contrast to e.g. Linux, there's no /proc directory on modern FreeBSD (at least not by default). Most of the information you'd usually get from procfs is set or retrieved using sysctl(8). This allows access to a hierarchical MIB with just about any information you'll need. Some examples:

hw.physmem: 8413745152
kern.maxfiles: 256767
kern.boottime: { sec = 1613061579, usec = 955761 } Thu Feb 11 17:39:39 2021
kern.geom.label.gptid.enable: 0
vm.loadavg: { 0.56 0.42 0.34 }
vm.stats.vm.v_kthreads: 37
vm.swap_total: 8589934592
vfs.zfs.min_auto_ashift: 12
net.inet.ip.forwarding: 0
debug.kdb.break_to_debugger: 0

All that kind of stuff (over 5,000 sysctls on FreeBSD 12.x). Often it's obvious what a sysctl represents, but sometimes a little research is necessary...

@GuillaumeGomez Do you still remember what information you had trouble finding?

GuillaumeGomez commented 3 years ago

I had actually mostly issues with the different types needed. The fields seem to depend from one BSD to another, making it really difficult to figure out how to generalize it. However, it's been 4 years now or even more that I gave it a try, so I don't remember anything more specific. But I remember for sure encountering multiples issues (mostly around documentation, had to spend a lot of time reading source codes).

kraileth commented 3 years ago

Ah, I see. Well, this is true: As the BSDs are whole operating systems (unlike Linux), so there's no "add support for one, get the others for free". While they share common ancestry, they have diverged much over the years. 20 years ago a popular book about FreeBSD was published and rightfully claimed that much of what was covered would be useful for readers who wanted to get into OpenBSD or NetBSD instead. This clearly is no longer the case.

FreeBSD for example uses the GEOM storage framework which is unique even among the BSD family of operating systems. So even for things like detecting disks, there is no way to generalize it (not even the device names are the same across all BSDs!).

The documentation is usually pretty good, though. Sure, there are dark and dusty corners, but in general it's very useful.

@mjarkk: Did you start some work on this? If you ran into problems and have questions about FreeBSD, I'd be happy to help (however I'm just an admin and not a developer who knows Rust).

mjarkk commented 3 years ago

I kinda got stuk on getting a nice development environment running in freebsd and meanwhile kinda forgot this issue.
But now that you've brought this up again and i have more free time to spend soon i can give it a second try.
Maybe i should not go for the remote vscode code editor and just take the time to setup a desktop and run a editor just inside the vm :).

tarkhil commented 3 years ago

Well, maybe I just can build it somehow enabling linux procfs?

GuillaumeGomez commented 3 years ago

It needs to work out of the box on all freebsd installations. So no, you have to deal with the "default" environment. Have fun! :D

tarkhil commented 3 years ago

I do understand your point; but right now I need to run a program using a package using a package using sysinfo, so any workaround will go. Actualy, I do need to use sysinfo::{get_current_pid, set_open_files_limit, Pid, ProcessExt, System, SystemExt} - but run it already yesterday...

GuillaumeGomez commented 3 years ago

No I meant in case you add support for freebsd.

tarkhil commented 3 years ago

Why? `This OpenJDK implementation requires fdescfs(5) mounted on /dev/fd and procfs(5) mounted on /proc.

If you have not done it yet, please do the following:

    mount -t fdescfs fdesc /dev/fd
    mount -t procfs proc /proc

To make it permanent, you need the following lines in /etc/fstab:

    fdesc   /dev/fd         fdescfs         rw      0       0
    proc    /proc           procfs          rw      0       0

`

GuillaumeGomez commented 3 years ago

You can't ask sysinfo users on freebsd to install stuff in order to make sysinfo work. I refuse.

tarkhil commented 3 years ago

Not install, but enable. procfs and linux-compatible procfs exists in base FreeBSD, and only has to be mounted.

GuillaumeGomez commented 3 years ago

Same, it should work without requiring any change from the user.

kraileth commented 3 years ago

Enabling procfs is actually a fairly common thing on FreeBSD. Even packages like Bash ask you to do it. But some people prefer to not use procfs and they also have valid reasons for this.

tarkhil commented 3 years ago

Well, it's your software; but I'd prefer soft running with some extra setup to soft not running at all.

GuillaumeGomez commented 3 years ago

You can simply have a fallback like we have on windows or mac. Getting system information is really random. So if there is procfs available, just use it, otherwise, try your best? XD

tarkhil commented 3 years ago

But I need to BUILD sysinfo!

mjarkk commented 3 years ago

@tarkhil welp there is one solution.. get your code editor up and start writing support for FreeBSD :)
I'm going to look into this upcoming weekend unless @tarkhil wants to write some code hehe

ryanavella commented 3 years ago

I've been looking into this, and I think @kraileth is correct about sysctl. It should provide everything you'd be able to get from /proc.

Here are some findings:

GuillaumeGomez commented 3 years ago

Thanks for the information!

Do you also know how to get information for processes, network and disk info too by any chance?

kraileth commented 3 years ago

For disk info you can have a look at sysctl kern.geom.confxml. It will output some XML that contains about all the info that you probably want about drives, partitions, etc. What info about network and processes are you looking for?

GuillaumeGomez commented 3 years ago

Also, please note that even with all this information, it'll require me a lot of time before implementing anything. I'm quite short in time and setting up a freebsd VM and develop anything inside it doesn't like something that will be done easily.

ryanavella commented 3 years ago

I'm a little new to FreeBSD, so not entirely sure on networks and processes. I'm learning as I go. If I have free time next week, I can see how far I'm able to get to a usable PR.

It may be possible to leverage the existing Apple code, but we'd need to trim out things that are Mach-specific. Same with Linux and the non-POSIX-y parts.

kraileth commented 3 years ago

@GuillaumeGomez I can offer to set up a FreeBSD VM for you if that helps. You'd just have to tell me exactly what you need and to mail me a public SSH key.

@ryanavella Have a look at netstat(1), it should be able to provide the required info. I'd also recommend to take a look at libxo(3), a formating library that is supported by netstat (that way you can have it output e.g. XML or JSON which is of course better to parse than standard command output). For processes you should get relevant info with procstat(1) (which also supports libxo).

GuillaumeGomez commented 3 years ago

@kraileth I intend to build one myself with virtualbox so then I can make my stuff work somehow, but thanks for the suggestion!

@ryanavella I'm not sure much of mac can be reused. Maybe the users and disk but the rest seems very apple specific. But thanks in advance in any case!

ryanavella commented 3 years ago

Wow, this was a lot more involved than I expected. A lot of the code I was able to leverage from Apple, but some required researching libprocstat and various system calls. Unfortunately the libc crate is lacking for FreeBSD, so I had to handcode some of the FFI.

Users are finished. System/process stuff is halfway done. I haven't even looked at networks, disks, or components yet.

I still have a few outstanding questions which are halting progress, and which I couldn't find documented anywhere:

GuillaumeGomez commented 3 years ago

Unfortunately the libc crate is lacking for FreeBSD, so I had to handcode some of the FFI.

It's fine, don't worry. It happened a lot of times in sysinfo already. Generally I add FFI in sysinfo, make a release and then send a PR to libc.

Users are finished. System/process stuff is halfway done. I haven't even looked at networks, disks, or components yet.

Nice, you're moving forward quite fast. :)

Does FreeBSD distinguish between free and available memory?

No idea.

Does the vm.swap_total sysctl return total swap, or total available swap? (docs are ambiguous here)

For reference, here is what freebsd docs say:

Corresponding values are available through sysctl vm.swap_total, that gives the total bytes available for swapping

So super confusing... Only one solution: check the values with swap being used...

Is there a way to calculate all desired swap values on FreeBSD?

No idea.

For all my "no idea" answers, I recommend to check how htop does it: https://github.com/htop-dev/htop/. For example they get swap info here.

GuillaumeGomez commented 2 years ago

I started working on it (you can see where I am: https://github.com/GuillaumeGomez/sysinfo/compare/freebsd?expand=1). I added the needed items in libc and I was busy fixing bugs on rustdoc and gtk-rs but I'll come back to it in the next days. If you want you can start looking on how to list disks or how to get network information. Any PR is very welcome. :)

EDIT: I'm not sure if my freebsd branch is building... I can make it compile so you can work on it if you want?

tarkhil commented 2 years ago

I can't. I've fixed one error

diff --git a/src/freebsd/system.rs b/src/freebsd/system.rs
index 39c777b..9fb33fb 100644
--- a/src/freebsd/system.rs
+++ b/src/freebsd/system.rs
@@ -141,7 +141,7 @@ impl SystemExt for System {

     fn refresh_processes(&mut self) {
         // KERN_PROC_PROC for a specific process (and then it requires the pid as 4th value in mib).
-        let mut mib = [libc::CTL_KERN, libc::KERN_PROC, KERN_PROC_ALL];
+        let mut mib = [libc::CTL_KERN, libc::KERN_PROC, libc::KERN_PROC_ALL];
         let mut size = 0;
         let ret = libc::sysctl(mib.as_mut_ptr(), 3, ::std::ptr::null_mut(), &mut size,
                                ::std::ptr::null_mut(), 0);

But I'm stuck for now on next

error[E0425]: cannot find function `refresh_procs` in this scope
   --> src/freebsd/system.rs:270:5
    |
270 |     refresh_procs(entry, path.join(Path::new("task")), page_size_kb, pid);
    |     ^^^^^^^^^^^^^ not found in this scope

at least until morning.

GuillaumeGomez commented 2 years ago

Sorry, I meant that I can fix it so it can compile so you can work on it. ;)

tarkhil commented 2 years ago

Please do it. Learning rust by trying to make someone's code to compile is a bit too harsh way! I'll return to work in 9-10 hours.

GuillaumeGomez commented 2 years ago

Done. I'll only push compiling code on this branch from now on. Now you can use it for developing any non-System related things. :)

dveeden commented 2 years ago

For disks, sysctl -a kern.geom.conftxt outputs this:

kern.geom.conftxt: 0 DISK ada2 3000592982016 512 hd 16 sc 63
1 PART ada2p3 2998443966464 512 i 3 o 2148532224 ty freebsd-zfs xs GPT xt 516e7cba-6ecf-11d6-8ff8-00022d09712b
1 PART ada2p2 2147483648 512 i 2 o 1048576 ty freebsd-swap xs GPT xt 516e7cb5-6ecf-11d6-8ff8-00022d09712b
1 PART ada2p1 524288 512 i 1 o 20480 ty freebsd-boot xs GPT xt 83bd6b9d-7f41-11dc-be0b-001560b84f0f
2 LABEL gpt/gptboot2 524288 512 i 0 o 0
0 DISK ada1 3000592982016 512 hd 16 sc 63
1 PART ada1p3 2998443966464 512 i 3 o 2148532224 ty freebsd-zfs xs GPT xt 516e7cba-6ecf-11d6-8ff8-00022d09712b
1 PART ada1p2 2147483648 512 i 2 o 1048576 ty freebsd-swap xs GPT xt 516e7cb5-6ecf-11d6-8ff8-00022d09712b
1 PART ada1p1 524288 512 i 1 o 20480 ty freebsd-boot xs GPT xt 83bd6b9d-7f41-11dc-be0b-001560b84f0f
2 LABEL gpt/gptboot1 524288 512 i 0 o 0
0 DISK ada0 3000592982016 512 hd 16 sc 63
1 LABEL diskid/DISK-WD-WCC4N2TV1YA0 3000592982016 512 i 0 o 0
1 PART ada0p3 2998443966464 512 i 3 o 2148532224 ty freebsd-zfs xs GPT xt 516e7cba-6ecf-11d6-8ff8-00022d09712b
1 PART ada0p2 2147483648 512 i 2 o 1048576 ty freebsd-swap xs GPT xt 516e7cb5-6ecf-11d6-8ff8-00022d09712b
1 PART ada0p1 524288 512 i 1 o 20480 ty freebsd-boot xs GPT xt 83bd6b9d-7f41-11dc-be0b-001560b84f0f
2 LABEL gpt/gptboot0 524288 512 i 0 o 0

There is also kern.geom.confxml, which is similar, but in XML instead of "TXT".

And sudo diskinfo -v /dev/ada0 for me returns:

/dev/ada0
    512             # sectorsize
    3000592982016   # mediasize in bytes (2.7T)
    5860533168      # mediasize in sectors
    4096            # stripesize
    0               # stripeoffset
    5814021         # Cylinders according to firmware.
    16              # Heads according to firmware.
    63              # Sectors according to firmware.
    WDC WD30EZRX-22D8PB0    # Disk descr.
    WD-WCC4N2TV1YA0 # Disk ident.
    ahcich3         # Attachment
    No              # TRIM/UNMAP support
    5400            # Rotation rate in RPM
    Not_Zoned       # Zone Mode

And then there is the gpart command.

https://docs.freebsd.org/en/books/handbook/disks/ has some more info.

Something like https://github.com/cemeyer/freebsd-geom-rs might be useful.

Hope this helps a bit.

dveeden commented 2 years ago

For network info there is getifaddrs and the usual ifconfig and things like sysctl -a dev.igb.0 (where igb is the intel gigabit driver)

This might be useful: https://docs.rs/nix/0.23.0/nix/ifaddrs/index.html

GuillaumeGomez commented 2 years ago

@dveeden Thanks for the information! It'll be very useful. :)