The article in the Ghost in the Shell series was the first post on my blog, so while I was busy by writing various server related articles and recently the FreeBSD Desktop series its about time for the Part 2 of the Ghost in the Shell series.
You may want to check other articles in the Ghost in the Shell series on the Ghost in the Shell – Global Page where you will find links to all episodes of the series along with table of contents for each episodeβs contents.
Lets start with something simple – yet powerful and time saving.
Alias with Arguments
One may of course write any function to do similar job, but keeping track and ‘maintaining’ all those functions becomes complicated and one has to organize itself. This partially applies to aliases, but they are smaller and easier to maintain then whole functions. In any modern shell an alias(1)
can also have arguments, while You will not be able to parse them as appropriate as with functions, they do the job for their basic use.
Here is an example of such alias(1)
with arguments.
% ls gfx/ info/ misc/ scripts/ tmp/ % alias lsg='ls | grep' % lsg gfx gfx/
Color grep(1) Patterns
As we already ‘touched’ the grep(1)
command topic, lets make it more usable by highlighting the found results in color. The ${GREP_COLOR}
variable is used for that purpose and it expects a number for a color, here is the table with number-color format.
Color Number Black 30 Red 31 Green 32 Yellow 33 Blue 34 Magenta 35 Cyan 36 White 37
You may as well use ‘bold’ output by adding ‘1;
‘ before the number, for example.
% echo ${GREP_COLOR} 1;31
You will also have to make an alias(1)
to grep(1)
with --color
argument, like that:
% alias grep='grep --color'
Here is how it looks in practice.
% export GREP_COLOR=31 % alias grep='grep --color' % dmesg | grep SMP FreeBSD/SMP: Multiprocessor System Detected: 2 CPUs FreeBSD/SMP: 1 package(s) x 2 core(s) SMP: AP CPU #1 Launched!
Here is how it looks on the xterm(1)
terminal.
Process Management
This one is very useful on any UNIX system, does not matter if its server or desktop.
These are commands and operands that will help us manage processes started by hand:
- &
- fg
- bg
- jobs
- kill
- disown
- nohup
- [CTRL]+[Z]
- [CTRL]+[C]
As you probably already know to start command ‘in the background’ – which means do what I tell you but do not block the terminal – you have to add ‘&
‘ (ampersand) at the end of such command. That command does not magically go away and as long as its running its visible by the jobs(1)
command. You may use ‘-l
‘ switch to also show the PID of background processes.
% galculator & [1] 8449 % jobs [1] + running galculator % jobs -l [1] + 8449 running galculator
Now, what of you forget to add ‘&
‘ (ampersand) at the end of command but you wanted to put it into the background? Hit [CTRL]+[Z] shortcut (Control key with ‘small’ Z letter) and the process will be put into the suspended state. Now you have several options, you can out that process into the background with bg(1)
command – by default it uses last suspended job – %1
, you can also bring it back into the foreground blocking the terminal with fg(1)
command. You can also list its state with jobs(1)
and of course kill(1)
it either with PID showed by jobs -l
command or by specifying the process number – %1
in that case.
Here is an example.
% galculator ^Z zsh: suspended galculator % jobs [1] + suspended galculator % bg [1] + continued galculator % jobs -l [1] + 72892 running galculator % kill %1 [1] + terminated galculator %
While fg(1)
and bg(1)
allow you to put command in the background or foreground respectively when the process is in suspended state, one may ask how to ‘switch’ a process to suspended state while its already running in the background. Its done with kill -17
signal called SIGSTOP
. You can also bring back such suspended process to running state with kill -19
signal called SIGCONT
… or just again use fg(1)
or bg(1)
command. Other difference between fg(1)
/bg(1)
commands and more ‘direct’ kill -17
/kill -19
commands are that kill(1)
does not inform the user what has changed to the process. You may as well use kill -SIGCONT
syntax or kill -s SIGCONT
if that is more readable for you.
% galculator ^Z zsh: suspended galculator % bg [1] + continued galculator % xcalc ^Z zsh: suspended xcalc % jobs -l [1] - 19537 running galculator [2] + 20563 suspended xcalc % kill -17 %1 [1] + suspended (signal) galculator % jobs -l [1] + 19537 suspended (signal) galculator [2] - 20563 suspended xcalc % kill -SIGCONT %1 % bg %2 [2] - continued xcalc % jobs -l [1] + 19537 running galculator [2] - 20563 running xcalc
Also check man kill
and man signal
for more information.
What about disown(1)
then? Its a ‘magic’ helper when you start some long running jobs directly at the terminal without Screen or Tmux and you need to disconnect that terminal, for example because you are taking your laptop with you. When you do this – depending on the settings of the current shell – the processes in the background may be killed or ‘moved’ to PID 1 (the init(1)
of course) as the PPID (Parent PID). To achieve that we will used that disown(1)
command. Once you ‘disown’ a process it will no longer be show by the jobs(1)
command, but it will run ‘pinned’ to the init(1)
process after you disconnect the terminal session.
% galculator ^Z zsh: suspended galculator % bg [1] + continued galculator % jobs -l [1] + 98556 running galculator % disown %1 % jobs -l % pgrep galculator 98556 % pstree -p 98556 ββ¬β 00001 root /sbin/init -- βββ¬β 48708 vermaden xterm βββ¬β 52463 vermaden -zsh (zsh) ββββ 98556 vermaden galculator
Now its still pinned to the shell in the xterm(1)
terminal. After we close the xterm(1)
window (or kill that zsh(1)
shell) it will switch to init(1)
as PPID (Parent PID).
% pstree -p 98556 ββ¬β 00001 root /sbin/init -- ββββ 98556 vermaden galculator % pgrep -P 1 galculator 98556
We are left with nohup(1)
then, when and why to use it as we already has great disown(1)
magic? Well, disown(1)
is not always available, so when You need to put some command into the long background run and disconnect after it its the best possible option. By default the nohup(1)
command will log the output of started command into the nohup.out
file. Remember that nohup(1)
will still run the process in the foreground, to put it into the background use ‘&
‘ (ampersand) or [CTRL]+[Z] with bg(1)
combo.
% nohup galculator appending output to nohup.out ^Z zsh: suspended nohup galculator % bg [1] + continued nohup galculator % jobs -l [1] + 22322 running nohup galculator % pstree -p 22322 ββ¬β 00001 root /sbin/init -- βββ¬β 89568 vermaden xterm βββ¬β 91486 vermaden -zsh (zsh) ββββ 22322 vermaden galculator
… and after disconnect out process switched to init(1)
as PPID.
% pstree -p 22322 ββ¬β 00001 root /sbin/init -- ββββ 22322 vermaden galculator
You may of course end a running process in the foreground with [CTRL]+[C] shortcut, but that is probably already known to you. I just mention it for the ‘completeness’ of the guide.
% galculator ^C %
Which Which
While the which(1)
command shows the full path of the executable found in the first directory of the ${PATH}
variable, it also shows what alias is used for that command it there is one. One may ask how then to find information about absolute executable path if it shows and alias(1)
instead. Well, you have to use unalias(1)
on that command, so which(1)
would be showing full path again.
% which caja caja: aliased to caja --browser --no-desktop % unalias caja % which caja /usr/local/bin/caja
Also be sure to check Smylers comment below about the difference between shell builtin which and /usr/bin/which command.
The difference is that by typing which you are executing your shell builtin command (ZSH in my case) which also takes aliases into account. If you want to omit the unalias part then use /usr/bin/which which will ignore any existing aliases.
% which caja caja: aliased to caja --browser --no-desktop % /usr/bin/which caja /usr/local/bin/caja
Record Session
If you have used PuTTY or MobaXterm in your work, then you appreciate the possibility of saving the terminal output to a file, foe example for the documentation purposes. This is also available ‘natively’ in the shell by using the script(1)
command. Remember that script(1)
will record also ‘special’ characters like colors, so to properly ‘replay’ the session you may want to either use script(1)
or cat(1)
commands for that or use less
with -R
argument.
Here is example recorded script(1)
session.
% script script.out Script started, output file is script.out % ls gfx info misc scripts tmp unix.png % uname -spr FreeBSD 11.2-RELEASE amd64 % exit Script done, output file is script.out % cat script.out Script started on Sun Jul 8 08:24:06 2018 You have mail. % ls | grep gfx gfx % uname -spr FreeBSD 11.2-RELEASE amd64 % exit exit Script done on Sun Jul 8 08:24:20 2018 % less -R script.out Script started on Sun Jul 8 08:24:06 2018 You have mail. % ls | grep gfx gfx % uname -spr FreeBSD 11.2-RELEASE amd64 % exit exit Script done on Sun Jul 8 08:24:20 2018 % less script.out Script started on Sun Jul 8 08:24:06 2018 You have mail. % ls | grep gfx ESC[1;31mgfxESC[00mESC[K % uname -spr FreeBSD 11.2-RELEASE amd64 % exit exit Script done on Sun Jul 8 08:24:20 2018
Edit Command Before Executing
Sometimes you have long multi-line command to execute, so often it is crafted in you favorite ${EDITOR}
and then pasted into the terminal. To omit copying and pasting yo may want to check fc(1)
command which serves similar purpose. After you type a command, for example simple ls(1)
command, and then you type fc(1)
command, then fc(1)
will take that ls(1)
command into your favorite text editor from ${EDITOR}
variable, will allow you to edit it and if you save and exit the that editor, it will execute it.
Lets see how it behave by example.
% ls gfx books download scripts % fc
Now you are taken into the ${EDITOR} which is vi(1) in my case.
1 ls ~ ~ ~ /tmp/zsh999EQ6: unmodified: line 1
Lets made some changes.
1 ls -l \ 2 -h ~ ~ ~ ~ :wq
After you hit [ENTER] it will exit from ${EDITOR}
and execute that command.
total 6181 drwxr-xr-x 87 vermaden vermaden 87B 2017.12.18 15:30 books/ drwxr-xr-x 12 vermaden vermaden 12B 2018.06.19 16:02 download/ drwxr-xr-x 19 vermaden vermaden 20B 2018.05.24 11:52 gfx/ drwx------ 12 vermaden vermaden 310B 2018.07.07 03:23 scripts/
You may show that command by pressing [Up] key to check what has been executed.
% ls -l -h
Edit or Just View
When working in multi-admin environment – especially while debugging – one admin may block other admin’s work by using vi(1)
– or just their favorite editor to ‘browse’ the file contents. Good practice in that case is using more(1)
or less(1)
instead of vi(1)
, but that frustrates some admins to type vi(1)
again if they need to change something.
… and by the way, on FreeBSD more(1)
is less(1)
π
% uname -spr FreeBSD 11.2-RELEASE amd64 % ls -i `which less` `which more` 492318 /usr/bin/less 492318 /usr/bin/more
A blocked ‘example’ is shown below when the second admin wanted to browse the /etc/rc.conf
file while the first one already did that.
# vim /etc/rc.conf E325: ATTENTION Found a swap file by the name "/etc/.rc.conf.swp" owned by: root dated: Sun Jul 8 08:38:35 2018 file name: /etc/rc.conf modified: no user name: root host name: t420s.local process ID: 54219 (still running) While opening file "/etc/rc.conf" dated: Fri Jul 6 00:51:11 2018 (1) Another program may be editing the same file. If this is the case, be careful not to end up with two different instances of the same file when making changes. Quit, or continue with caution. (2) An edit session for this file crashed. If this is the case, use ":recover" or "vim -r /etc/rc.conf" to recover the changes (see ":help recovery"). If you did this already, delete the swap file "/etc/.rc.conf.swp" to avoid this message. Swap file "/etc/.rc.conf.swp" already exists! [O]pen Read-Only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort:
This is where less(1)
comes handy because of you open a file in it, you do not ‘block’ access to it and if you need to edit something just hi [V] key (small ‘v’ letter). It will open that file in your ${EDITOR}
editor and you can make any changes now.
Reset
Last but not least, often when you paste ‘too much’ into the terminal it becomes ‘fragile’ or ‘broken’. To reset it into the ‘stable’ and ‘proper’ state just use the reset(1)
command.
% reset
Hope You find it useful, see you at the Part 3 sometime π
Aliases can’t take arguments on most shells. The only reason your lsg example is working is because $1 is unquoted and expanding to an empty string.
LikeLike
You are right, I fixed that, thanks for pointing that out.
LikeLike
Pingback: In Other BSDs for 2018/07/21 – DragonFly BSD Digest
Pingback: Ghost in the Shell – Part 3 | vermaden
Pingback: FreeBSD Desktop – Part 16 – Configuration – Pause Any Application | vermaden
Hi. I think the βWhich Whichβ section is, quite understandably, confusing the two separate commands both called π ππππ.
π ππππ(π·) usually refers to /πππ/π ππππ. That’s an external program that knows nothing of your shell aliases. So if you run /πππ/π ππππΒ ππππ you will always see /πππ/πππππ/πππ/ππππ.
But shells also have a built-in command called π ππππ, and built-in commands take precedence over external commands, so that’s the one that runs by default when you just type π ππππ. In your case, it looks like you’re using ZSh, which chooses to report aliases. Try the same example in Bash and you don’t get that.
In either shell you can find out what will run when you type ππππ, taking aliases into account, with ππ’ππΒ ππππ.
And to run the external π ππππ(π·) without having to know its path, you can do πππππππ π ππππ.
Summary:
β’ πππππππ π ππππΒ πππ β always reports the underlying path, ignoring any aliases
β’ ππ’ππΒ πππ β always takes aliases into account
β’ π ππππΒ πππ β might do either of the above, depending on which shell you’re using
LikeLike
Hi,
thank you for the comment.
I will try to mention that in the update.
Its similar with other shell builtins like time or echo for example, but yes its not obvious.
Regards,
vermaden
LikeLike
Pingback: Ghost in the Shell – Part 1 | π π ΄ππΌπ°π³π π
Pingback: βGhostlyβ tips (2) | 0ddn1x: tricks with *nix
Pingback: Ghost in the Shell – Part 4 | ππππππππ
Awesome! Its genuinely amazing piece of writing,
I have got much clear idea concerning from this
paragraph.
LikeLiked by 1 person
Thank You π
LikeLike