Documentation
¶
Overview ¶
Package lxkns discovers Linux kernel namespaces (of types cgroup, ipc, mount, net, pid, user, and uts). This package discovers namespaces not only when processes have joined them, but also when namespaces have been bind-mounted or are only referenced anymore by process file descriptors.
In case of PID and user namespaces, lxkns additionally discovers their hierarchies, except when running on a really ancient kernel before 4.9. Furthermore, for user namespaces the owning user ID and the owned namespaces will be discovered too.
And finally, lxkns relates namespaces to the "leading" (or "root") processes joined to them; this relationship is basically derived from on the process tree hierarchy.
The namespace discovery process can be controlled in several aspects, according to the range of discovery of namespace types and places to search namespaces for, according to the needs of API users of the lxkns package.
Discovery ¶
A namespace discovery is just a single call to function lxkns.Discover(). Additionally, there's a one-time support function call to reexec.CheckAction() required as early as possible in main().
import ( "github.com/thediveo/gons/reexec" "github.com/thediveo/lxkns" ) func main() { reexec.CheckAction() ... allns := lxkns.Discover(lxkns.FullDiscovery) ... }
Technical note: in order to discover namespaces in some locations, such as bind-mounted namespaces, lxkns needs to fork the process it used from in, in order to switch the forked copy into other mount namespaces for further discovery. In order to implement this mechanism as painless as possible, process using lxkns need to call reexec.CheckAction() as early as possible from their main().
Information Model, Base Level ¶
Not totally unexpectedly, the lxkns discovery information model at its most basic level comprises namespaces. In the previous code snippet, the information model returned is stored in the "allns" variable for further processing. The result organizes the namespaces found by type. For instance, the following code snippet prints all namespaces, sorted first by type and then by namespace identifier:
// Iterate over all 7 types of Linux-kernel namespaces, then over all // namespaces of a given type... for nsidx := range allns.Namespaces { for _, ns := range allns.SortedNamespaces(lxkns.NamespaceTypeIndex(nsidx)) { println(ns.Type().Name(), ns.ID().Ino) } }
Because namespaces have no order defined, the discovery results "list" the namespaces in per-type maps, indexed by namespace identifiers. For convenience, SortedNamespaces() returns the namespaces of a specific type in a slice instead of a map, sorted numerically by the namespace identifiers (that is, sorting by inode numbers, ignoring dev IDs at this time).
Technically, these namespace identifiers are tuples consisting of 64bit unsigned inode numbers and (~64bit) device ID numbers, and come from the special "nsfs" namespace filesystem integrated with the Linux kernel. And before someone tries: nope, the nsfs cannot be mounted; and it even does not appear in the kernel's list of namespaces.
Unprivileged Discovery and How To Not Panic ¶
While it is possible to discover namespaces without root privileges, this won't return the full set of namespaces in a Linux host. The reason is that while an unprivileged discovery is allowed to see some basic information about all processes in the system, it is not allowed to query the namespaces such privileged processes are joined too. In addition, an unprivileged discovery may turn up namespaces (for instance, when bind-mounted) for which the identifier is discovered, but further information, such as the parent or child namespaces for PID and user namespaces, is undiscoverable.
Users of the lxkns information model thus must be prepared to handle incomplete information yielded by unprivileged lxkns.Discover() calls. In particular, applications must be prepared to handle:
- more than a single "initial" namespace per type of namespace,
- PID and user namespaces without a parent namespace,
- namespaces without owning user namespaces,
- processes not related to any namespace.
In consequence, always check interface values and pointers for nil values like a pro. You can find many examples in the sources for the "lsuns", "lspidns", and "pidtree" CLI tools (inside the cmd sub-package).
In-Capabilities ¶
It is possible to run full discoveries without being root, when executing the discovery process with the following effective capabilities:
- CAP_SYS_PTRACE -- no joking here, that's what needed for reading namespace references from /proc/[PID]/ns/*
- CAP_SYS_CHROOT -- for mount namespace switching
- CAP_SYS_ADMIN -- for mount namespace switching
Considering that especially CAP_SYS_PTRACE being essential there's probably not much difference to "just be root" in the end, unless you want show off your "capabilities capabilities".
Namespace Hierarchies ¶
PID and user namespaces form separate and independent namespaces hierarchies. This parent-child hierarchy is exposed through the lxkns.Hierarchy interface of the discovered namespaces.
Please note that lxkns represents namespaces often using the lxkns.Namespace interface when the specific type of namespace doesn't matter. In case of PID and user-type namespaces an lxkns.Namespace can be "converted" into an interface value of type lxkns.Hierarchy using a type assertion, in order to access the particular namespace hierarchy.
// If it's a PID or user namespace, then we can turn a "Namespace" // into an "Hierarchy" in order to access hierarchy information. if hns, ok := ns.(lxkns.Hierarchy); ok { if hns.Parent() != nil { ... } for _, childns := range hns.Children() { ... } }
Ownership ¶
User namespaces play the central role in controlling the access of processes to other namespaces as well as the capabilities process gain when allowed to join user namespaces. A comprehensive discussion of the rules and their ramifications is beyond this package documentation. For starters, please refer to the man page for user_namespaces(7), http://man7.org/linux/man-pages/man7/user_namespaces.7.html.
The controlling role of user namespaces show up in the discovery information model as owner-owneds relationships: user namespaces own non-user namespaces. And non-user namespaces are owned by user namespaces, the "ownings". In case you are now scratching your head "why the Gopher" the owned namespaces are referred to as "ownings": welcome to the wonderful Gopher world of "er"-ers, where interface method naming conventions create wonderful identifier art.
If a namespace interface value represents a user-type namespace, then it can be "converted" into an lxkns.Ownership interface value using a type assertion. This interface discloses which namespaces are owned by a particular user namespace. Please note that this does not include child user namespaces, use Hierarchy.Children() instead.
// Get the user namespace -owned-> namespaces relationships. if owns, ok := ns.(lxkns.Ownership); ok { for _, ownedns := range owns.Ownings() { ... } }
In the opposite direction, the owner of a namespace can be directly queried via the lxkns.Namespace interface (again, only for non-user namespaces):
// Get the namespace -owned by-> user namespace relationship. ownerns := ns.Owner()
When asking a user namespace for its owner, the parent user namespace is returned in accordance with the Linux ioctl()s for discovering the ownership of namespaces.
Namespaces and Processes ¶
The lxkns discovery information model also relates processes to namespaces, and vice versa. After all, processes are probably the main source for discovering namespaces.
For this reason, the discovery results (in "allns" in case of the above discovery code example) not only list the namespaces found, but also a snapshot of the process tree at discovery time (please relax now, as this is a snapshot of the "tree", not of all the processes themselves).
// Get the init(1) process representation. initprocess := allns.Processes[lxkns.PIDType(1)] for _, childprocess := range initprocess.Children() { ... }
Please note that the process tree information is for convenience; it's not a replacement for the famous gopsutil package in many use cases. However, the process tree information show which namespaces are used by (or "joined by") which particular processes.
// Show all namespaces joined by a specific process, such as init(1). for nsidx := lxkns.MountNS; nsidx < lxkns.NamespaceTypesCount; nsidx++ { println(initprocess.Namespaces[nsidx].String()) }
It's also possible, given a specific namespace, to find the processes joined to this namespace. However, the lxkns information model optimizes this relationship information on the assumption that in many situations not the list of all processes joined to a namespace is needed, but actually only the so-called "leader" process or processes.
A leader process of namespace X is the process topmost in the process tree hierarchy of processes joined to namespace X. It is perfectly valid for a namespace to have more than one leader process joined to it. An example is a container with its own processes joined to the container namespaces, and an additional "visiting" process also joined to one or several namespaces of this container. The lxkns information then is able to correctly handle and represent such system states.
// Show the leader processes joined to the initial user namespace. for _, leaders := range initprocess.Namespaces[lxkns.UserNS].Leaders() { ... }
Architecture ¶
Please find more details about the lxkns information model in the architectural documents: https://github.com/TheDiveO/lxkns/blob/master/docs/architecture.md.
Index ¶
- Constants
- Variables
- func ReexecIntoAction(actionname string, namespaces []Namespace, result interface{}) (err error)
- func ReexecIntoActionEnv(actionname string, namespaces []Namespace, envvars []string, ...) (err error)
- type AllNamespaces
- type BindmountedNamespaceInfo
- type DiscoverOpts
- type DiscoveryResult
- type Hierarchy
- type HierarchyConfigurer
- type Namespace
- type NamespaceConfigurer
- type NamespaceMap
- type NamespaceStringer
- type NamespaceTypeIndex
- type NamespacedPID
- type NamespacedPIDs
- type NamespacesSet
- type Ownership
- type PIDMap
- type PIDType
- type Process
- type ProcessListByPID
- type ProcessTable
Constants ¶
const SemVersion = "0.12.0"
SemVersion is the semantic version string of the lxkns module.
Variables ¶
var FullDiscovery = DiscoverOpts{}
FullDiscovery sets the discovery options to a full and thus extensive discovery process.
var NoDiscovery = DiscoverOpts{ SkipProcs: true, SkipTasks: true, SkipFds: true, SkipBindmounts: true, SkipHierarchy: true, SkipOwnership: true, }
NoDiscovery set the discovery options to not discover anything. This option set can be used to start from when only a few chosen discovery methods are to be enabled.
var TypeIndexLexicalOrder = [NamespaceTypesCount]NamespaceTypeIndex{ CgroupNS, IPCNS, MountNS, NetNS, PIDNS, TimeNS, UserNS, UTSNS, }
TypeIndexLexicalOrder contains Namespace type indices in lexical order.
var TypesByIndex = [NamespaceTypesCount]species.NamespaceType{ species.CLONE_NEWNS, species.CLONE_NEWCGROUP, species.CLONE_NEWUTS, species.CLONE_NEWIPC, species.CLONE_NEWUSER, species.CLONE_NEWPID, species.CLONE_NEWNET, species.CLONE_NEWTIME, }
TypesByIndex maps Allnamespaces array indices to their corresponding Linux' kernel namespace clone() syscall constants.
Functions ¶
func ReexecIntoAction ¶ added in v0.9.0
ReexecIntoAction forks and then re-executes this process in order to run a specific action (indicated by actionname) in a set of (different) Linux kernel namespaces. The stdout result of running the action is then deserialized as JSON into the specified result element.
func ReexecIntoActionEnv ¶ added in v0.9.0
func ReexecIntoActionEnv(actionname string, namespaces []Namespace, envvars []string, result interface{}) (err error)
ReexecIntoActionEnv forks and then re-executes this process in order to run a specific action (indicated by actionname) in a set of (different) Linux kernel namespaces. It also passes the additional environment variables specified in envvars. The stdout result of running the action is then deserialized as JSON into the specified result element.
Types ¶
type AllNamespaces ¶ added in v0.9.0
type AllNamespaces [NamespaceTypesCount]NamespaceMap
AllNamespaces contains separate NamespaceMaps for all types of Linux kernel namespaces. This type allows package functions to work on multiple namespace types simultaneously in order to optimize traversal of the /proc filesystem, bind-mounts, et cetera. AllNamespaces thus stores "all" namespaces that could be discovered in the system, subject to discovery filtering.
type BindmountedNamespaceInfo ¶ added in v0.11.0
type BindmountedNamespaceInfo struct { ID species.NamespaceID `json:"id"` Type species.NamespaceType `json:"type"` Path string `json:"path"` OwnernsID species.NamespaceID `json:"ownernsid"` }
BindmountedNamespaceInfo describes a bind-mounted namespace in some (other) mount namespace, including the owning user namespace ID, so we can later correctly set up the ownership relations in the discovery results.
type DiscoverOpts ¶ added in v0.9.0
type DiscoverOpts struct { // The types of namespaces to discover: this is an OR'ed combination of // Linux kernel namespace constants, such as CLONE_NEWNS, CLONE_NEWNET, et // cetera. If zero, defaults to discovering all namespaces. NamespaceTypes species.NamespaceType // Where to scan (or not scan) for signs of namespaces? SkipProcs bool // Don't scan processes. SkipTasks bool // Don't scan threads, a.k.a. tasks. SkipFds bool // Don't scan process file descriptors for references to namespaces. SkipBindmounts bool // Don't scan for bind-mounted namespaces. SkipHierarchy bool // Don't discover the hierarchy of PID and user namespaces. SkipOwnership bool // Don't discover the ownership of non-user namespaces. }
DiscoverOpts gives control over the extend and thus time and resources spent on discovering Linux kernel namespaces, their relationships between them, and with processes.
type DiscoveryResult ¶ added in v0.9.0
type DiscoveryResult struct { Options DiscoverOpts // options used during discovery. Namespaces AllNamespaces // all discovered namespaces, subject to filtering according to Options. InitialNamespaces NamespacesSet // the 7 initial namespaces. UserNSRoots []Namespace // the topmost user namespace(s) in the hierarchy PIDNSRoots []Namespace // the topmost PID namespace(s) in the hierarchy Processes ProcessTable // processes checked for namespaces. }
DiscoveryResult stores the results of a tour through Linux processes and kernel namespaces.
func Discover ¶ added in v0.9.0
func Discover(opts DiscoverOpts) *DiscoveryResult
Discover returns the Linux kernel namespaces found, based on discovery options specified in the call. The discovery results also specify the initial namespaces, as well the process table/tree on which the discovery bases at least in part.
func (*DiscoveryResult) SortedNamespaces ¶ added in v0.9.0
func (dr *DiscoveryResult) SortedNamespaces(nsidx NamespaceTypeIndex) []Namespace
SortedNamespaces returns a sorted list of discovered namespaces of the specified type. The namespaces are sorted by their identifier, which is an inode number (on the special "nsfs" filesystem), ignoring a namespace's device ID.
type Hierarchy ¶ added in v0.9.0
type Hierarchy interface { // Parent returns the parent user or PID namespace of this user or PID // namespace. If there is no parent namespace or the parent namespace in // inaccessible, then Parent returns nil. Parent() Hierarchy // Children returns a list of child PID or user namespaces for this PID or // user namespace. Children() []Hierarchy }
Hierarchy informs about the parent-child relationships of PID and user namespaces.
func SortChildNamespaces ¶ added in v0.9.0
SortChildNamespaces returns a sorted copy of a list of hierarchical namespaces. The namespaces are sorted by their namespace ids in ascending order. Please note that the list itself is flat, but this function can only be used on hierarchical namespaces (PID, user).
type HierarchyConfigurer ¶ added in v0.9.0
HierarchyConfigurer allows discovery mechanisms to configure the information hold by hierarchical namespaces.
type Namespace ¶ added in v0.9.0
type Namespace interface { // ID returns the unique identifier of this Linux-kernel namespace. This // identifier is basically a tuple consisting of an inode number from the // special "nsfs" namespace filesystem inside the Linux kernel, together // with the device ID of that nsfs filesystem. IDs cannot be set as only the // Linux allocates and manages them. ID() species.NamespaceID // Type returns the type of namespace in form of one of the NamespaceType, such // as species.CLONE_NEWNS, species.CLONE_NEWCGROUP, et cetera. Type() species.NamespaceType // Owner returns the user namespace "owning" this namespace. For user // namespaces, Owner always returns nil; use Hierarchy.Parent() instead, as // the owner of a user namespace is its parent user namespace. Owner() Ownership // Ref returns a filesystem path suitable for referencing this namespace. A zero // ref indicates that there is no reference path available: this is the case for // "hidden" PID and user namespaces sandwiched in between PID or user namespaces // where reference paths are available, because these other namespaces have // processes joined to them, or are either bind-mounted or fd-referenced. Hidden // PID namespaces can appear only when there is no process in any of their child // namespaces and the child PID namespace(s) is bind-mounted or fd-references // (the parent PID namespace is then kept alive because the child PID namespaces // are kept alive). Ref() string // Leaders returns an unsorted list of Process-es which are joined to this // namespace and which are the topmost processes in the process tree still // joined to this namespace. Leaders() []*Process // LeaderPIDs returns the list of leader PIDs. This is a convenience method for // those use cases where just a list of leader process PIDs is needed, but not // the leader Process objects themselves. LeaderPIDs() []PIDType // "leader" process PIDs only. // Ealdorman returns the most senior leader process. The "most senior" // process is the one which was created at the earliest, based on the start // times from /proc/[PID]/stat. Me thinks, me has read too many Bernard // Cornwell books. Wyrd bið ful aræd. Ealdorman() *Process // String describes this namespace with type, id, joined leader processes, // and optionally information about owner, children, parent. String() string }
Namespace represents a Linux kernel namespace in terms of its unique identifier, type, owning user namespace, joined (leader) processes, and some more.
func NewNamespace ¶ added in v0.9.0
func NewNamespace(nstype species.NamespaceType, nsid species.NamespaceID, ref string) Namespace
NewNamespace returns a new zero'ed namespace object suitable for the specified type of namespace. Now this is a real-world case where the "nongonformist" rule of "accept interfaces, return structs" doesn't make sense, because struct types don't support polymorphism. On the other hand, thousands of blog posts and SO answers cannot be wrong, more so, the more upvotes they accumulated ;)
func SortNamespaces ¶ added in v0.9.0
SortNamespaces returns a sorted copy of a list of namespaces. The namespaces are sorted by their namespace ids in ascending order.
func SortedNamespaces ¶ added in v0.9.0
func SortedNamespaces(nsmap NamespaceMap) []Namespace
SortedNamespaces returns the namespaces from a map sorted.
type NamespaceConfigurer ¶ added in v0.9.0
type NamespaceConfigurer interface { AddLeader(proc *Process) // adds yet another self-styled leader. SetRef(string) // sets a filesystem path for referencing this namespace. DetectOwner(nsf *ops.NamespaceFile) // detects owning user namespace id. SetOwner(usernsid species.NamespaceID) // sets the owning user namespace id directly. ResolveOwner(usernsmap NamespaceMap) // resolves owner ns id into object reference. }
NamespaceConfigurer allows discovery mechanisms to set up the information for a namespace. This is a lxkns-internal interface needed by other lxkns subpackages.
type NamespaceMap ¶ added in v0.9.0
type NamespaceMap map[species.NamespaceID]Namespace
NamespaceMap indexes a bunch of Namespaces by their identifiers. Usually, namespace indices will contain only namespaces of the same type.
type NamespaceStringer ¶ added in v0.9.0
type NamespaceStringer interface { fmt.Stringer // TypeIDString describes this instance of a Linux kernel namespace just by // its type and identifier, and nothing else. TypeIDString() string }
NamespaceStringer describes a namespace either in its descriptive form when using the well-known String() method, or in a terse format when going for TypeIDString(), which only describes the type and identifier of a namespace.
type NamespaceTypeIndex ¶ added in v0.9.0
type NamespaceTypeIndex int
NamespaceTypeIndex is an array index type for Linux kernel namespace types. It is used with the AllNamespaces type, which is an array of namespace maps, one map "id->namespace object" for each type of Linux kernel namespace. NamespaceTypeIndex must not be confused with the Linux' kernel namespace clone() syscall constants as typed as NamespaceType instead.
const ( MountNS NamespaceTypeIndex = iota // array index for mount namespaces map CgroupNS // array index for cgroup namespaces map UTSNS // array index for UTS namespaces map IPCNS // array index for IPC namespaces map UserNS // array index for user namespaces map PIDNS // array index for PID namespaces map NetNS // array index for net namespaces map TimeNS // array index for time namespaces map NamespaceTypesCount // number of namespace types )
Set of indices into AllNamespaces arrays, one for each type of Linux kernel namespace.
func TypeIndex ¶ added in v0.9.0
func TypeIndex(nstype species.NamespaceType) NamespaceTypeIndex
TypeIndex returns the AllNamespaces array index corresponding with the specified Linux' kernel clone() syscall namespace constant. For instance, for CLONE_NEWNET the index NetNS is then returned.
type NamespacedPID ¶ added in v0.9.0
type NamespacedPID struct { PIDNS Namespace // PID namespace ID for PID. PID PIDType // PID within PID namespace (of ID). }
NamespacedPID is PID in the context of a specific PID namespace.
type NamespacedPIDs ¶ added in v0.9.0
type NamespacedPIDs []NamespacedPID
NamespacedPIDs is a list of PIDs for the same process, but in different PID namespaces. The order of the list is undefined.
func (NamespacedPIDs) PIDs ¶ added in v0.9.0
func (ns NamespacedPIDs) PIDs() []PIDType
PIDs just returns the different PIDs assigned to a single process in different PID namespaces, without the namespaces. This is a convenience function for those lazy cases where just the PID list is wanted, but no PID namespace details.
type NamespacesSet ¶ added in v0.9.0
type NamespacesSet [NamespaceTypesCount]Namespace
NamespacesSet contains a Namespace reference of each type exactly once. For instance, it represents the set of 7 namespaces a process will always be joined ("attached", ...) to. Processes cannot be not attached to each type of Linux kernel namespace.
type Ownership ¶ added in v0.9.0
type Ownership interface { // UID returns the user ID of the process that created this user namespace. UID() int // Ownings returns all namespaces owned by this user namespace, with the // exception of user namespaces. "Owned" user namespaces are actually child // user namespaces, so they are returned through Hierarchy.Children() // instead. Ownings() AllNamespaces }
Ownership informs about the owning user ID, as well as the namespaces owned by a specific user namespace. Only user namespaces can execute Ownership.
type PIDMap ¶ added in v0.9.0
type PIDMap struct {
// contains filtered or unexported fields
}
PIDMap maps a single namespaced PID to the list of PIDs for this process in different PID namespaces. Further PIDMap methods then allow simple translation of PIDs between different PID namespaces.
func NewPIDMap ¶ added in v0.9.0
func NewPIDMap(res *DiscoveryResult) *PIDMap
NewPIDMap returns a new PID map based on the specified discovery results and further information gathered from the /proc filesystem.
func (*PIDMap) NamespacedPIDs ¶ added in v0.9.0
func (pm *PIDMap) NamespacedPIDs(pid PIDType, from Namespace) NamespacedPIDs
NamespacedPIDs returns for a specific namespaced PID the list of all PIDs the corresponding process has been given in different PID namespaces. Returns nil if the PID doesn't exist in the specified PID namespace. The list is ordered from the topmost PID namespace down to the leaf PID namespace to which a process actually is joined to.
type PIDType ¶ added in v0.9.0
type PIDType int32
PIDType expresses things more clearly. And no, that's not a "PidType" since "PID" is an acronym (https://en.wikipedia.org/wiki/Acronym), but neither an abbreviation, nor an ordinary word (yet/still) in itself.
func NSpid ¶ added in v0.9.0
NSpid returns the list of namespaced PIDs for the process proc, based on information from the /proc filesystem (the "NSpid:" field in particular). NSpid only returns the list of PIDs, but not the corresponding PID namespaces; this is because the Linux kernel doesn't give us the namespace information as part of the process status. Instead, a caller (such as NewPIDMap) needs to combine a namespaced PIDs list with the hierarchy own PID namespaces to calculate the correct namespacing.
type Process ¶ added in v0.9.0
type Process struct { PID PIDType // this process' identifier. PPID PIDType // parent's process identifier. Parent *Process // our parent's process description. Children []*Process // child processes. Name string // synthesized name of process. Cmdline []string // command line of process. Namespaces NamespacesSet // the 7 namespaces joined by this process. Starttime uint64 // Time of process start, since the Kernel boot epoch. }
Process represents our very limited view and even more limited interest in a specific Linux process. Well, the limitation comes from what we need for namespace discovery to be useful.
func NewProcess ¶ added in v0.9.0
NewProcess returns a Process object describing certain properties of the Linux process with the specified PID. In particular, the parent PID and the name of the process, as well as the command line.
func (*Process) Basename ¶ added in v0.9.0
Basename returns the process executable name with the directory stripped off, similar to what basename(1) does when applied to the "$0" argument. In case the basename would be empty, then the process name is returned instead as fallback.
type ProcessListByPID ¶ added in v0.9.0
type ProcessListByPID []*Process
ProcessListByPID is a type alias for sorting slices of *Process by their PIDs in numerically ascending order.
func (ProcessListByPID) Len ¶ added in v0.9.0
func (l ProcessListByPID) Len() int
func (ProcessListByPID) Less ¶ added in v0.9.0
func (l ProcessListByPID) Less(i, j int) bool
func (ProcessListByPID) Swap ¶ added in v0.9.0
func (l ProcessListByPID) Swap(i, j int)
type ProcessTable ¶ added in v0.9.0
ProcessTable maps PIDs to their Process descriptions, allowing for quick lookups.
func NewProcessTable ¶ added in v0.9.0
func NewProcessTable() (pt ProcessTable)
NewProcessTable takes returns the currently available processes (as usual, without tasks=threads). The process table is in fact a map, indexed by PIDs.
Source Files
¶
Directories
¶
Path | Synopsis |
---|---|
cmd
|
|
internal/pkg/cli
Package cli handles registering CLI flags via a plug-in mechanism.
|
Package cli handles registering CLI flags via a plug-in mechanism. |
internal/pkg/filter
Package filter provides CLI-controlled filtering of namespaces by type.
|
Package filter provides CLI-controlled filtering of namespaces by type. |
internal/pkg/style
Package style styles text output of the CLI commands with foreground and background colors, as well as different text styles (bold, italics, ...).
|
Package style styles text output of the CLI commands with foreground and background colors, as well as different text styles (bold, italics, ...). |
internal/test/getstdout
Package getstdout captures os.Stdout and os.Stderr while executing a specified function, returning the captured output afterwards.
|
Package getstdout captures os.Stdout and os.Stderr while executing a specified function, returning the captured output afterwards. |
lspidns
lspidns lists the tree of PID namespaces, optionally with their owning user namespaces.
|
lspidns lists the tree of PID namespaces, optionally with their owning user namespaces. |
lsuns
lsuns lists the tree of user namespaces, optionally with the other namespaces they own.
|
lsuns lists the tree of user namespaces, optionally with the other namespaces they own. |
pidtree
pidtree displays a tree (or only a single branch) of processes together with their PID namespaces, and additionally also shows the local PIDs of processes (where applicable).
|
pidtree displays a tree (or only a single branch) of processes together with their PID namespaces, and additionally also shows the local PIDs of processes (where applicable). |
examples
|
|
Package nstest provides testing support in the context of Linux kernel namespaces.
|
Package nstest provides testing support in the context of Linux kernel namespaces. |
Package ops provides a Golang-idiomatic API to query and switching operations on Linux-kernel namespaces.
|
Package ops provides a Golang-idiomatic API to query and switching operations on Linux-kernel namespaces. |
Package species defines the type constants and type names of the 7 Linux kernel namespace types ("species").
|
Package species defines the type constants and type names of the 7 Linux kernel namespace types ("species"). |