// Copyright 2015 CoreOS, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package util contains utility functions related to systemd that applications // can use to check things like whether systemd is running. Note that some of // these functions attempt to manually load systemd libraries at runtime rather // than linking against them. package util import ( "fmt" "io/ioutil" "os" "strings" ) var ( ErrNoCGO = fmt.Errorf("go-systemd built with CGO disabled") ) // GetRunningSlice attempts to retrieve the name of the systemd slice in which // the current process is running. // This function is a wrapper around the libsystemd C library; if it cannot be // opened, an error is returned. func GetRunningSlice() (string, error) { return getRunningSlice() } // RunningFromSystemService tries to detect whether the current process has // been invoked from a system service. The condition for this is whether the // process is _not_ a user process. User processes are those running in session // scopes or under per-user `systemd --user` instances. // // To avoid false positives on systems without `pam_systemd` (which is // responsible for creating user sessions), this function also uses a heuristic // to detect whether it's being invoked from a session leader process. This is // the case if the current process is executed directly from a service file // (e.g. with `ExecStart=/this/cmd`). Note that this heuristic will fail if the // command is instead launched in a subshell or similar so that it is not // session leader (e.g. `ExecStart=/bin/bash -c "/this/cmd"`) // // This function is a wrapper around the libsystemd C library; if this is // unable to successfully open a handle to the library for any reason (e.g. it // cannot be found), an error will be returned. func RunningFromSystemService() (bool, error) { return runningFromSystemService() } // CurrentUnitName attempts to retrieve the name of the systemd system unit // from which the calling process has been invoked. It wraps the systemd // `sd_pid_get_unit` call, with the same caveat: for processes not part of a // systemd system unit, this function will return an error. func CurrentUnitName() (string, error) { return currentUnitName() } // IsRunningSystemd checks whether the host was booted with systemd as its init // system. This functions similarly to systemd's `sd_booted(3)`: internally, it // checks whether /run/systemd/system/ exists and is a directory. // http://www.freedesktop.org/software/systemd/man/sd_booted.html func IsRunningSystemd() bool { fi, err := os.Lstat("/run/systemd/system") if err != nil { return false } return fi.IsDir() } // GetMachineID returns a host's 128-bit machine ID as a string. This functions // similarly to systemd's `sd_id128_get_machine`: internally, it simply reads // the contents of /etc/machine-id // http://www.freedesktop.org/software/systemd/man/sd_id128_get_machine.html func GetMachineID() (string, error) { machineID, err := ioutil.ReadFile("/etc/machine-id") if err != nil { return "", fmt.Errorf("failed to read /etc/machine-id: %v", err) } return strings.TrimSpace(string(machineID)), nil }