gopsutil is a transitive dependency of another project that I am integrating
into an internal build system. We target multiple platforms and as a part
of the build system for the large internal repo, we calculate the build
graph used to determine what targets have changed and need to be build /
tested as a single DAG for all platforms.
gopsutil currently does not form a DAG if linux and any other platform are
considered at the same time. linux is the only platform where the process
package imports the host package.
To remove this cycle, the relevant methods have been moved to internal/common
with the linux build tag and are consumed the host and process packages.
On Linux, most golang programs do not run as root (or at least, they should not),
by default, the kernels uses strict permissions, so most userland programs cannot
read `/sys/class/dmi/id/product_uuid`. However, programs such as Consul are relying
on it to get fixed IDs, instead they have a different ID on each boot.
We propose to use `/etc/machine-id` as fallback https://www.freedesktop.org/software/systemd/man/machine-id.html
In order to fix this, this patch does the following:
- if `/sys/class/dmi/id/product_uuid` can be read, use it for HostID
- else if `/etc/machine-id` exists and has 32 chars, use it and add '-' to have the same format as product_uuid
- finally, if notthing works, use the `kernel.random.boot_id`
This will greatly increase the number of programs having correct behaviour when
those rely on having a fixed HostID.
This will fix the following issues:
- https://github.com/shirou/gopsutil/issues/350
- https://github.com/hashicorp/consul/issues/4741
When fetching stats on all processes at once there's a non-trivial amount of
time spent in the `BootTime` call. But since this value should never change
during a live process, we can use a cached version for all subsequent calls.
This is mostly intended for Linux, where we are returning the OS version
in the PlatformVersion field, which seems reasonable. Often it is still
useful to know which Linux kernel is running.
For FreeBSD and Darwin the kernel version matches the platform version,
since they previously used the kernel version for the platform version.
For Windows the kernel version is empty, since there is no clear way
to determine it.
before falling back to kernel.random.boot_id.
`/sys/class/dmi/id/product_uuid` is still managed by permissions, so
for root-run processes where `/sys/class/dmi/id/product_uuid` is
available, the host's UUID will be used instead, otherwise the UUID
from kernel.random.boot_id will be used instead.
On supported hosts the value returned is a UUID (case preserving
from the value of the underlying OS).
For Linux this is generated once, randomly per boot. For FreeBSD and
Darwin this is a more durable value that should persist across reboots.
host_darwin does the same filtering. Not doing this gives us some rather strange
entries that likely aren't what we want.
Before:
{"user":"reboot","terminal":"~","host":"3.10.0-327.4.5.el7.x86_64","started":1454378260}
{"user":"LOGIN","terminal":"ttyS0","host":"","started":1454378270}
{"user":"LOGIN","terminal":"tty1","host":"","started":1454378270}
{"user":"runlevel","terminal":"~","host":"3.10.0-327.4.5.el7.x86_64","started":1454378276}
{"user":"root","terminal":"pts/0","host":"vpn","started":1454404513}
After:
{"user":"root","terminal":"pts/0","host":"vpn","started":1454404513}
Package common wasn't used for public functions. Place it in an
internal directory to prevent other packages from using.
Remove the distributed references to "HOST_PROC" and "HOST_SYS"
consts and combine into a common function. This also helps so that
if a env var is defined with a trailing slash all will continue to
work as expected.
Fixes #100