khenaidoo | ffe076b | 2019-01-15 16:08:08 -0500 | [diff] [blame^] | 1 | // Copyright 2015 CoreOS, Inc. |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
| 15 | // Package util contains utility functions related to systemd that applications |
| 16 | // can use to check things like whether systemd is running. Note that some of |
| 17 | // these functions attempt to manually load systemd libraries at runtime rather |
| 18 | // than linking against them. |
| 19 | package util |
| 20 | |
| 21 | import ( |
| 22 | "fmt" |
| 23 | "io/ioutil" |
| 24 | "os" |
| 25 | "strings" |
| 26 | ) |
| 27 | |
| 28 | var ( |
| 29 | ErrNoCGO = fmt.Errorf("go-systemd built with CGO disabled") |
| 30 | ) |
| 31 | |
| 32 | // GetRunningSlice attempts to retrieve the name of the systemd slice in which |
| 33 | // the current process is running. |
| 34 | // This function is a wrapper around the libsystemd C library; if it cannot be |
| 35 | // opened, an error is returned. |
| 36 | func GetRunningSlice() (string, error) { |
| 37 | return getRunningSlice() |
| 38 | } |
| 39 | |
| 40 | // RunningFromSystemService tries to detect whether the current process has |
| 41 | // been invoked from a system service. The condition for this is whether the |
| 42 | // process is _not_ a user process. User processes are those running in session |
| 43 | // scopes or under per-user `systemd --user` instances. |
| 44 | // |
| 45 | // To avoid false positives on systems without `pam_systemd` (which is |
| 46 | // responsible for creating user sessions), this function also uses a heuristic |
| 47 | // to detect whether it's being invoked from a session leader process. This is |
| 48 | // the case if the current process is executed directly from a service file |
| 49 | // (e.g. with `ExecStart=/this/cmd`). Note that this heuristic will fail if the |
| 50 | // command is instead launched in a subshell or similar so that it is not |
| 51 | // session leader (e.g. `ExecStart=/bin/bash -c "/this/cmd"`) |
| 52 | // |
| 53 | // This function is a wrapper around the libsystemd C library; if this is |
| 54 | // unable to successfully open a handle to the library for any reason (e.g. it |
| 55 | // cannot be found), an error will be returned. |
| 56 | func RunningFromSystemService() (bool, error) { |
| 57 | return runningFromSystemService() |
| 58 | } |
| 59 | |
| 60 | // CurrentUnitName attempts to retrieve the name of the systemd system unit |
| 61 | // from which the calling process has been invoked. It wraps the systemd |
| 62 | // `sd_pid_get_unit` call, with the same caveat: for processes not part of a |
| 63 | // systemd system unit, this function will return an error. |
| 64 | func CurrentUnitName() (string, error) { |
| 65 | return currentUnitName() |
| 66 | } |
| 67 | |
| 68 | // IsRunningSystemd checks whether the host was booted with systemd as its init |
| 69 | // system. This functions similarly to systemd's `sd_booted(3)`: internally, it |
| 70 | // checks whether /run/systemd/system/ exists and is a directory. |
| 71 | // http://www.freedesktop.org/software/systemd/man/sd_booted.html |
| 72 | func IsRunningSystemd() bool { |
| 73 | fi, err := os.Lstat("/run/systemd/system") |
| 74 | if err != nil { |
| 75 | return false |
| 76 | } |
| 77 | return fi.IsDir() |
| 78 | } |
| 79 | |
| 80 | // GetMachineID returns a host's 128-bit machine ID as a string. This functions |
| 81 | // similarly to systemd's `sd_id128_get_machine`: internally, it simply reads |
| 82 | // the contents of /etc/machine-id |
| 83 | // http://www.freedesktop.org/software/systemd/man/sd_id128_get_machine.html |
| 84 | func GetMachineID() (string, error) { |
| 85 | machineID, err := ioutil.ReadFile("/etc/machine-id") |
| 86 | if err != nil { |
| 87 | return "", fmt.Errorf("failed to read /etc/machine-id: %v", err) |
| 88 | } |
| 89 | return strings.TrimSpace(string(machineID)), nil |
| 90 | } |