1
1
package clistat
2
2
3
3
import (
4
- "github.com/elastic/go-sysinfo"
5
- "golang.org/x/xerrors"
4
+ "bufio"
5
+ "bytes"
6
+ "os"
6
7
"runtime"
7
8
"strconv"
8
9
"strings"
9
- "tailscale.com/types/ptr"
10
10
"time"
11
11
12
+ "github.com/elastic/go-sysinfo"
13
+ "golang.org/x/xerrors"
14
+ "tailscale.com/types/ptr"
15
+
12
16
sysinfotypes "github.com/elastic/go-sysinfo/types"
13
17
)
14
18
19
+ const procOneCgroup = "/proc/1/cgroup"
20
+
15
21
// Result is a generic result type for a statistic.
16
22
// Total is the total amount of the resource available.
17
23
// It is nil if the resource is not a finite quantity.
@@ -125,7 +131,7 @@ func (s *Statter) Uptime() (*Result, error) {
125
131
Total : nil , // Is time a finite quantity? For this purpose, no.
126
132
}
127
133
128
- if ok := IsContainerized (); ok != nil && * ok {
134
+ if ok , err := IsContainerized (); err == nil && ok {
129
135
procStat , err := sysinfo .Process (1 )
130
136
if err != nil {
131
137
return nil , xerrors .Errorf ("get pid 1 info: %w" , err )
@@ -152,11 +158,43 @@ func (s *Statter) ContainerMemory() (*Result, error) {
152
158
}
153
159
154
160
// IsContainerized returns whether the host is containerized.
155
- // This wraps the elastic/go-sysinfo library.
156
- func IsContainerized () * bool {
157
- hi , err := sysinfo .Host ()
161
+ // This is adapted from https://github.com/elastic/go-sysinfo/tree/main/providers/linux/container.go#L31
162
+ // with modifications to support Sysbox containers.
163
+ func IsContainerized () (bool , error ) {
164
+ data , err := os .ReadFile (procOneCgroup )
165
+ if err != nil {
166
+ if os .IsNotExist (err ) { // how?
167
+ return false , nil
168
+ }
169
+ return false , xerrors .Errorf ("read process cgroups: %w" , err )
170
+ }
171
+
172
+ s := bufio .NewScanner (bytes .NewReader (data ))
173
+ for s .Scan () {
174
+ line := s .Bytes ()
175
+ if bytes .Contains (line , []byte ("docker" )) ||
176
+ bytes .Contains (line , []byte (".slice" )) ||
177
+ bytes .Contains (line , []byte ("lxc" )) ||
178
+ bytes .Contains (line , []byte ("kubepods" )) {
179
+ return true , nil
180
+ }
181
+ }
182
+
183
+ // Last-ditch effort to detect Sysbox containers.
184
+ // Check if we have anything mounted as type sysboxfs in /proc/mounts
185
+ data , err = os .ReadFile ("/proc/mounts" )
158
186
if err != nil {
159
- return nil
187
+ return false , xerrors . Errorf ( "read /proc/mounts: %w" , err )
160
188
}
161
- return hi .Info ().Containerized
189
+
190
+ s = bufio .NewScanner (bytes .NewReader (data ))
191
+ for s .Scan () {
192
+ line := s .Bytes ()
193
+ if bytes .HasPrefix (line , []byte ("sysboxfs" )) {
194
+ return true , nil
195
+ }
196
+ }
197
+
198
+ // If we get here, we are _probably_ not running in a container.
199
+ return false , nil
162
200
}
0 commit comments