Demonstrate uname Options


Personally, I never made a habit of using the uname command on Linux.


uname is a basic utility which is primarily used to print the kernel version. But, there are other options available.


I typically use the -a option which prints everything.


But, today, I sat down and tried every option to see what they all did. Note that uname with no supplied option implies -s.


To make displaying every option easier, I wrote a PowerShell one-liner that demonstrates every uname option.


You can find an explanation of each part in the sections below.


As you can see, if I want just the kernel version then I can use uname -r


@('a','s','n','r','v','m','p','i','o') | foreach-object { "$_`n$(uname -$_)`n" }


a
Linux john.local 6.10.5-1-default #1 SMP PREEMPT_DYNAMIC Fri Aug 16 11:15:41 UTC 2024 (30fd964) x86_64 x86_64 x86_64 GNU/Linux

s
Linux

n
john.local

r
6.10.5-1-default

v
#1 SMP PREEMPT_DYNAMIC Fri Aug 16 11:15:41 UTC 2024 (30fd964)

m
x86_64

p
x86_64

i
x86_64

o
GNU/Linux




uname


Let's start with the uname manual page.


man uname 


Once the manual page loads, you will see the command options in the description section. This gives us the letters that we will use later as inputs. For example, -a or -s.


UNAME(1)                         User Commands                         UNAME(1)

NAME
       uname - print system information

SYNOPSIS
       uname [OPTION]...

DESCRIPTION
       Print certain system information.  With no OPTION, same as -s.

       -a, --all
              print all information, in the following order, except omit -p and
              -i if unknown:

       -s, --kernel-name
              print the kernel name

       -n, --nodename
              print the network node hostname

       -r, --kernel-release
              print the kernel release

       -v, --kernel-version
              print the kernel version

       -m, --machine
              print the machine hardware name

       -p, --processor
              print the processor type (non-portable)

       -i, --hardware-platform
              print the hardware platform (non-portable)

       -o, --operating-system
              print the operating system

       --help display this help and exit

       --version
              output version information and exit




Array


From a programmer's perspective, the letters change for each uname option listed above: a, s, n, r, ... So, I'll want to collect those letters and use them later.


Using the PowerShell array operator @( ) allows us to create an array of single-character strings. For example, 'a' and 's' are full string objects in PowerShell instead of chars like in other programming languages.


Commas separate the elements of the array.


@('a','s','n','r','v','m','p','i','o')




Pipeline


PowerShell typically processes information in a pipeline. Along with objects, pipelines are a central feature of PowerShell and are regularly used.


Conceptually, pipelines connect the output from one command to the input of another command.


It is also important to understand that, in PowerShell, collections like our array are passed down the pipeline one array element at a time. So, two things will happen to the next command in the pipeline. One, the next command in the pipeline will be invoked once for each value passing through the pipeline. And, two, the command will receive one element of data as input during each invocation. So, in our case, the next command in the pipeline will receive one letter with each invocation.


Sending collections down the pipeline one element at a time is a useful default behavior. And this lets pipelines take the general form of:



That's what we will do in our example today.


Since PowerShell is object-oriented, even data--like our array--have implicit outputs. What that means is, simply putting the array at the beginning of a pipeline will pass the individual array elements (letters in our case) to the next command in the pipeline.


So a simple solution to our problem would be to feed the letters in the array into a command which used each letter as a uname option. That's the basic approach I'll follow here.


To tell PowerShell to link the array with a following command as a pipeline, we use the pipe symbol or vertical bar | On US keyboards, you typically hold Shift and press Backslash together to produce a pipe symbol.


In our example, the pipe will connect the implicit output of the array--the letters--and the input to our command.


@('a','s','n','r','v','m','p','i','o') | # some command


Also, to refer to each input in later pipeline commands, we will use the $_ automatic variable. $_ represents the current object traveling down the pipeline. For example, $_ might represent the letter 'a' when pipeline command is invoked for the first time. This gives you a convenient way to refer to input from the pipeline inside your command. Just type dollar sign and underscore to refer to the automatic variable.


@('a','s','n','r','v','m','p','i','o') | ForEach-Object { "The current letter in the pipeline is $_" } 


The current letter in the pipeline is a
The current letter in the pipeline is s
The current letter in the pipeline is n
The current letter in the pipeline is r
The current letter in the pipeline is v
The current letter in the pipeline is m
The current letter in the pipeline is p
The current letter in the pipeline is i
The current letter in the pipeline is o




ForEach-Object


ForEach-Object is a PowerShell cmdlet (pronounced "command-let"). cmdlets are PowerShell commands.


ForEach-Object allows you to add custom code to a pipeline. Inside a ForEach-Object code block, you can write any valid PowerShell code. Code blocks consist of PowerShell code between matching curly braces { }


For example, below is how our pipeline would look with ForEach-Object added to the end.


Note: cmdlet names are not case-sensitive.


@('a','s','n','r','v','m','p','i','o') | foreach-object { <# custom code #> }



Output String


Let's focus on getting our custom code to work for one letter of input. And, let's start with something simple like a string. We'll start with just one of the uname options.


We create a PowerShell string by placing double-quotes before and after the text.


"a"


Now, inside our string, let's pretend to invoke uname.


"uname -a"


If we were to invoke that command for real then we would receive the output of the command. That's normal. But, in our case, it might be confusing to see only the output of commands without seeing the commands themselves.


If we want to see the commands then we'll have to add them ourselves to the output. Or, as I've done, I will just output the letter so that you can tell which uname option was used.


So, let's add a placeholder to our mock-up. And let that placeholder represent the option used in the command. So, if I use the -a option then I should see both the option 'a', and the output of the command.


For now, let's use the following as our string.


"(the option a) (the output from uname -a)"


One thing we can do with our string is put the option and command output on different lines.


Programming languages typically have an escape sequence that allows you to insert a newline into string output. PowerShell uses the escape sequence `n where ` is the backtick character and n is the literal 'n' character. Backtick can be typed by pressing the tilde ~ key which is to the left of the 1 key.


Note: For clarity, the backtick ` key produces backtick by default. And holding Shift and pressing backtick produces tilde ~ instead.


We can use `n to separate the option from the output. And, we can add a newline to the end of the string to add a buffer between outputs.


"(the option a) `n (the output from uname -a) `n"


Let's run this and see how it behaves with our pipeline.


@('a','s','n','r','v','m','p','i','o') | foreach-object { "(the option a) `n (the output from uname -a) `n" }


(the option a) 
 (the output from uname -a) 

(the option a) 
 (the output from uname -a) 

(the option a) 
 (the output from uname -a) 

(the option a) 
 (the output from uname -a) 

(the option a) 
 (the output from uname -a) 

(the option a) 
 (the output from uname -a) 

(the option a) 
 (the output from uname -a) 

(the option a) 
 (the output from uname -a) 

(the option a) 
 (the output from uname -a) 


This output is basically correct.



Also, notice that I just have a simple string as the only object inside the code block { }. This works because ForEach-Object returns the string object. And, PowerShell implicitly prints the string without an explicit command to do so.



Continuing, let's try using the $_ automatic variable to replace our letter 'a' with the actual input.


@('a','s','n','r','v','m','p','i','o') | foreach-object { "$_ `n uname -$_ `n" }


a 
 uname -a 

s 
 uname -s 

n 
 uname -n 

r 
 uname -r 

v 
 uname -v 

m 
 uname -m 

p 
 uname -p 

i 
 uname -i 

o 
 uname -o 


I can see that the inputs are now being formatted by our string and output by the pipeline.




Subexpression Operator


At this point, the output string looks fine. And we just need to solve the problem of actually running the uname command with an option.


While ForEach-Object can run code directly, I've chosen to use a simple string as the only code within the code block.


So, let's continue with that string. And, let's try to run some code inside the string.


We can run code inside of a string with the subexpression operator $( ) For example, "$(uname -a)" runs the uname -a command.


And, if we keep the $_ automatic variable then we'll have a command that automatically updates for each letter in our array.


Note: Below, I've removed some spaces to match my original one-liner. If you prefer the spacing from the previous example then feel free to add the spaces back in.



This is the final command as shown at the top of the gemlog.


@('a','s','n','r','v','m','p','i','o') | foreach-object { "$_`n$(uname -$_)`n" }


a
Linux john.local 6.10.5-1-default #1 SMP PREEMPT_DYNAMIC Fri Aug 16 11:15:41 UTC 2024 (30fd964) x86_64 x86_64 x86_64 GNU/Linux

s
Linux

n
john.local

r
6.10.5-1-default

v
#1 SMP PREEMPT_DYNAMIC Fri Aug 16 11:15:41 UTC 2024 (30fd964)

m
x86_64

p
x86_64

i
x86_64

o
GNU/Linux


As you can now see, each option is provided by the array to the pipeline. And, ForEach-Object lets us run code against each value flowing down the pipeline: in this case, each letter.


The string in the code block outputs the uname option, uses a subexpression $( ) operator to run a command, and uses the `n escape sequence to put each output on its own line.




References


Linux man Command | Baeldung on Linux

uname | Arch Manual Pages

@( ) about_Arrays | Microsoft

about_Pipelines | Microsoft

$_ about_PSItem | Microsoft

ForEach-Object | Microsoft

{ } about_Script_Blocks | Microsoft

<# #> Comments | Language Specification | Microsoft

" " Strings | about_Quoting_Rules | Microsoft

`n about_Special_Characters | Microsoft

$( ) Subexpression Operator | about_Operators | Microsoft



Created: Tuesday, September 3, 2024

Updated: Tuesday, September 3, 2024




/gemlog/