I/O in Linux

Global variables and initialization files

  • Customizing the working environment has usually the following goals:
    • minimize the routine operations to ease the overall work
    • customize the working environment to best suite the user's needs
  • Working environment in Linux can be customized with
    • initialization files,
    • variables configured in these files and
    • with global variables
  • Usually when Linux program is started it reads
    • configured variables and global variables
    • initialization files found from user's home directory (usually hidden files starting with . character)
  • Initialization files in user's home directory include user specific environment settings and commands which can be utilized by running programs
  • Below is an example where user's home directory content is listed
testuser@ubuntu-PC:~$ ls -a
.           .bash_history  .cache  .local    .sudo_as_admin_successful
..          .bash_logout   data    .profile  .wget-hsts
backup.tar  .bashrc        .gnupg  sqlit
  • There are two types of variables in Linux:
    • Local variables
    • Global variables
  • Local variables can be referred only from active shell
  • Global variable values can be inherited to also to child processes
  • Global variable cannot be returned to normal variable
  • Variable name cannot start with a number
  • Important: All global variables are also local variables, but not all local variables are global variables!
  • Local or global variable values can be printed with echo command like in the example below
testuser@ubuntu-PC:~$ echo $MYVAR
100
  • Variable names are always case-sensitive and are started with $ character
  • Variable value can be set like in the following way:
testuser@ubuntu-PC:~$ myvar=200
testuser@ubuntu-PC:~$ echo $myvar
200
  • Local variables are loaded to user's working environment with export command
  • Below is an example of export command usage
  • Example: Let's create MYVAR variable and set it's value to 100. This variable will then be added to global variables. Global variables are then printed with env command
testuser@ubuntu-PC:~$ MYVAR=100
testuser@ubuntu-PC:~$ export MYVAR
testuser@ubuntu-PC:~$ env
SSH_CONNECTION=10.0.2.2 49172 10.0.2.4 22
LESSCLOSE=/usr/bin/lesspipe %s %s
LANG=en_US.UTF-8
XDG_SESSION_ID=3
USER=testuser
MYVAR=100
PWD=/home/testuser
HOME=/home/testuser
SSH_CLIENT=10.0.2.2 49172 22
XDG_DATA_DIRS=/usr/local/share:/usr/share:/var/lib/snapd/desktop
SSH_TTY=/dev/pts/0
MAIL=/var/mail/testuser
TERM=xterm
SHELL=/bin/bash
SHLVL=1
LOGNAME=testuser
XDG_RUNTIME_DIR=/run/user/1000
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/usr/local/bin
LESSOPEN=| /usr/bin/lesspipe %s
_=/usr/bin/env
  • Below are some examples of variable use
testuser@ubuntu-PC:~$ Firstname=James
testuser@ubuntu-PC:~$ Lastname=Tester
testuser@ubuntu-PC:~$ Fullname="${Firstname}, ${Lastname}"
testuser@ubuntu-PC:~$ echo $Fullname
James, Tester
testuser@ubuntu-PC:~$ Wizard="$Linus $(whoami) $Fullname"
testuser@ubuntu-PC:~$ echo Wizard
Wizard
testuser@ubuntu-PC:~$ echo $Wizard
testuser James, Tester
testuser@ubuntu-PC:~$ Linus="Username and fullname: "
testuser@ubuntu-PC:~$ echo $Wizard
testuser James, Tester
testuser@ubuntu-PC:~$ Wizard="$Linus $(whoami) $Fullname"
testuser@ubuntu-PC:~$ echo $Wizard
Fullname and username: testuser James, Tester
testuser@ubuntu-PC:~$
  • Some variable names are reserved and should not be used
  • Below is a table presenting variable names reserved for Bourne shell (Bash has also its own list of reserved variables)
Variable name Definition
CDPATH A colon-separated list of directories used as a search path for the cd built-in command.
HOME The current user's home directory; the default for the cd built-in. The value of this variable is also used by tilde expansion.
IFS A list of characters that separate fields; used when the shell splits words as part of expansion.
MAIL If this parameter is set to a file name and the MAILPATH variable is not set, Bash informs the user of the arrival of mail in the specified file.
MAILPATH A colon-separated list of file names which the shell periodically checks for new mail.
OPTARG The value of the last option argument processed by the getopts built-in.
OPTIND The index of the last option argument processed by the getopts built-in.
PATH A colon-separated list of directories in which the shell looks for commands.
PS1 The primary prompt string. The default value is "'\s-\v\$ '".
PS2 The secondary prompt string. The default value is "'> '".
  • Below is an example where the look of command prompt is customized with bash internal variable PS1
testuser@ubuntu-PC:~$ echo $PS1
\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\u@\h:\w\$
  • The following list can be used to describe the parameters used in the example above
Parameter Description
\t or \T Time (24h or 12h)
\d Date
\w Working directory
\h Computer name (host)
\u User name
\$ User prompt (# or $)
  • It is recommended to save the prompt customization command in one of the initialization files, for example

    • .bashrc in user's home directory
    • /etc/bash.bashrc when command should be used system wide
  • Below is an example where prompt is edited and then returned back to original setting

    1. Store the original prompt on a variable (PS_TEMP)
    2. Change the prompt
    3. Return the original from variable (PS_TEMP)
testuser@ubuntu-PC:~$ PS_TEMP=$PS1
testuser@ubuntu-PC:~$ PS1="\h $(pwd) \$ "
ubuntu-PC /home/testuser $
ubuntu-PC /home/testuser $ PS1=$PS_TEMP
testuser@ubuntu-PC:~$

Initialization files

  • Global variables should be stored in initialization/configuration files so user does not have make the changes again in each new session
  • Usually programs have program specific initialization files created during the installation of the program
  • These initialization files are usually the hidden files or directories starting with . character in user's home directory
  • Examples of initialization files:
    • .bashrc .vimrc .conkyrc .config/ .vim/
  • The most essential initialization files are the following:

    • /etc/profile
      • Includes system specific settings for all shells, which are common for all users: global variables (PATH, HOSTNAME, etc.) and other settings
    • .profile
      • User specific settings for all shells, for example LANG, PATH, program specific settings etc.
      • This file is stored in each user's home directory
      • File is read when shell is started during user's login process
    • /etc/bash.bashrc
      • Similar to /etc/profile, but includes settings only for bash shell
    • .bashrc
      • User specific settings for bash shell
      • This file is stored in each user's home directory
      • File is read every time shell is started (without login prompt) and always before any command is executed
  • Changes for initialization files are active after the next login or start of the shell

  • Changes can also be activated immediately with source command:
testuser@ubuntu-PC:~$ source /etc/profile
testuser@ubuntu-PC:~$ source /etc/bash.bashrc
testuser@ubuntu-PC:~$ source $HOME/.profile
testuser@ubuntu-PC:~$ source $HOME/.bashrc

Alias (Command shortcut)

  • Alias can be and is recommended to set for long commands used frequently
  • alias command can be used to print all defined aliases
testuser@ubuntu-PC:~$ alias
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
alias ls='ls --color=auto'
  • A new alias can be set with the following command
testuser@ubuntu-PC:~$ alias md=mkdir
testuser@ubuntu-PC:~$ alias mdp=’mkdir -p’
  • Important: When creating permanent aliases alias configuration should be included in either /etc/bash.bashrc or .bashrc file
  • Example of using alias command
testuser@ubuntu-PC:~$ alias md=mkdir
testuser@ubuntu-PC:~$ ls
backup.tar  data  sqlit
testuser@ubuntu-PC:~$ md alias-test
testuser@ubuntu-PC:~$ ls
alias-test  backup.tar  data  sqlit
  • Below is another example where alias configuration is stored in .bashrc file
testuser@ubuntu-PC:~$ echo "alias md='mkdir’" >> ~/.bashrc
testuser@ubuntu-PC:~$ echo "alias n='netstat -an | grep LISTEN | less'" >> ~/.bashrc
testuser@ubuntu-PC:~$ source ~/.bashrc
testuser@ubuntu-PC:~$ n
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
tcp6       0      0 :::22                   :::*                    LISTEN
unix  2      [ ACC ]     SEQPACKET  LISTENING     12867    /run/udev/control
unix  2      [ ACC ]     STREAM     LISTENING     23756    /run/user/1000/systemd/private
unix  2      [ ACC ]     STREAM     LISTENING     23760    /run/user/1000/gnupg/S.dirmngr
unix  2      [ ACC ]     STREAM     LISTENING     23761    /run/user/1000/gnupg/S.gpg-agent
unix  2      [ ACC ]     STREAM     LISTENING     23762    /run/user/1000/gnupg/S.gpg-agent.extra
unix  2      [ ACC ]     STREAM     LISTENING     23763    /run/user/1000/gnupg/S.gpg-agent.ssh
unix  2      [ ACC ]     STREAM     LISTENING     23764    /run/user/1000/gnupg/S.gpg-agent.browser

I/O channels (input, output)

  • There are three input/output channels in Unux process:
    • stdin: input channel where data is transferred to the process, usually through a keyboard attached to the computer
    • stdout: output channel for the process, which is dedicated usually for monitor attached to the computer by default
    • stderr: error channel for the process, which is dedicated for monitor attached to the computer by default

IO channels

  • All three I/O channels are pointing monitor or pseudoterminal by default
  • User may redirect the channels to point to a file like in the examples below

  • Example 1. Print to the file

command > file.txt
  • Example 2. Print to the end of the file
command >> file.txt
  • Example 3. Print stdout and stderr to the file
command >& file.txt
  • Example 4. Read from the file
command < file.txt
  • Below are some examples of I/O channel usage
testuser@ubuntu-PC:~$ ls
alias-test
testuser@ubuntu-PC:~$ w > monitoring.txt
testuser@ubuntu-PC:~$ ls
alias-test monitoring.txt
testuser@ubuntu-PC:~$ cat monitoring.txt
06:39:29 up  1:50,  2 users,  load average: 0.00, 0.00, 0.00
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU  WHAT
testuser tty1     -                05:05    1:34m  0.09s  0.03s -bash
testuser pts/0    10.0.2.2         05:05    0.00s  0.62s  0.00s w
testuser@ubuntu-PC:~$ ls
alias-test monitorointi.txt
testuser@ubuntu-PC:~$ cd..
cd..: command not found
testuser@ubuntu-PC:~$ cd.. >& error.txt
testuser@ubuntu-PC:~$ ls
alias-test  monitoring.txt error.txt
testuser@ubuntu-PC:~$ cat error.txt
cd..: command not found

Command chaining

  • Commands can be chained in the terminal, so that it is possible to execute multiple commands at the same time
  • This way the commands are run in order (from left to right) and their execution is determined by the use of logical operators
  • To chain commands, the following operators may be used:
    • ; → the command following this operator is run regardless of whether the preceding command has been succesfully executed
    • AND → the command following this operator is only executed if the preceding command is succesfully executed
    • OR → the command following this operator is only executed if the preceding command has failed
  • The logical operators are typed in the following way:

    • AND:
      • logical operator AND (&&)
    • OR:
      • logical operator OR (||)
  • Below are some examples of using command chaining

  • Example 1: Print the current date, logged in user and computer's name with single line
testuser@ubuntu-PC:~$ date && whoami && hostname
ThuSep26 10:33:06 UTC 2019
testuser
ubuntu
  • Example 2: Set variable and print the content of the variable to the screen
testuser@ubuntu-PC:~$ var="Date is $(date) and user is $(whoami)" ; echo $var
Date is Thu Sep26 10:38:54 UTC 2019 and user is testuser
  • Example 3: Try to create a directory called newdata under the /etc directory and inform user whether the command was executed successfully
testuser@ubuntu-PC:~$ mkdir /etc/newdata && echo "Directory was created" || echo "Failed" 
mkdir: cannot create directory "/etc/data": Permission denied
Failed
testuser@ubuntu:~$ sudo su
[sudo] password for testuser:
root@ubuntu-PC:~# mkdir /etc/data && echo "Directory was created" || echo "Failed"
Directory was created

Pipeline

  • In Unix-based operating systems pipe command can be used to redirect standard output for another command for example
  • Pipeline can be used with | character
  • Several pipelines can be run in a row
  • Standard output can be done in the beginning and at the end of the pipeline
  • The syntax of pipeline is the following:
command1 | command2
  • In this syntax example output from command1 (stdout) will be redirected as an input for command2 (stdin)
  • Both commands will be executed in two separate processes and the execution will be done simultaneously
  • Below are a list of different examples presenting the use of the pipeline

  • Example 1: Count logged in users (both local and remote)

    • w prints users (option -h without title information)
    • wc counts the rows from the input, which then equals the amount of logged in users
testuser@ubuntu-PC:~$ w -h | wc -l
2
  • Example 2: Print the content of /etc directory using less command
testuser@ubuntu-PC:~$ ls -la /etc | less
  • Example 3: Sort the user list, add row numbers and print output to the file called users.txt
testuser@ubuntu-PC:~$ w –h | sort | cat -b > users.txt
  • Example 4: Use cowsay program to print the current logged in user (program is installed first)
testuser@ubuntu-PC:~$ sudo apt install cowsay
testuser@ubuntu-PC:~$ cowsay Hello
 _______
< Hello >
 -------
       \     ^__^
        \    (oo)\_______
             (__)\      )\/\
                 ||----w |
                 ||     ||

testuser@ubuntu-PC:~$ whoami | cowsay
 __________
< testuser >
 ----------
          \   ^__^
           \  (oo)\_______
              (__)\       )\/\
                  ||----w |
                  ||     ||
  • Example 5: Use cowsay program to print the computer's name using luke-koala
testuser@ubuntu-PC:~$ cowsay -l
Cow files in /usr/share/cowsay/cows:
apt bud-frogs bunny calvin cheese cock cower daemon default dragon
dragon-and-cow duck elephant elephant-in-snake eyes flaming-sheep
ghostbusters gnu hellokitty kiss koala kosh luke-koala mech-and-cow
milkmoofasa moose pony pony-smaller ren sheep skeleton snowman stegosaurus
stimpy suse three-eyes turkey turtle tux unipony unipony-smaller vader
vader-koala www
testuser@ubuntu-PC:~$ echo $HOSTNAME | cowsay -f luke-koala
   ___________
  < ubuntu-PC >
   -----------
    \
     \          .
         ___   //
       {~._.~}//
        ( Y )K/
       ()~*~()
       (_)-(_)
       Luke
       Skywalker
       koala