6 minutes
Bashing
Some good bash basics and some nice bash tips to make everyday life easier
Really good place where to get detailed explanation what shell commands do is https://explainshell.com/ It’s basically colorize manpage and it has dark theme with random colors!
Since last post was too long I’ll try to keep this one as small as possible and picked only most used stuff
Back to basics
Let’s go over some basics before digging deeper into cool tricks
Chaining flags
Let’s take ls
as an example, everyone has used it, to see content of some directory
There can’t be anything more basic than that..
ls
mcsneaky@bunter ~/guide
└─$ ls
tempfile
Now, adding some flags, like wanting to see all the hidden files with extra data, like permissions dates etc in there and let’s make it human readable with
ls -l -a -h
mcsneaky@bunter ~/guide
└─$ ls -l -a
total 8
drwxr-xr-x 2 mcsneaky mcsneaky 4096 Aug 24 16:21 .
drwxr-xr-x 12 mcsneaky mcsneaky 4096 Aug 24 15:17 ..
-rw-r--r-- 1 mcsneaky mcsneaky 0 Aug 24 16:21 .hidden
-rw-r--r-- 1 mcsneaky mcsneaky 0 Aug 24 15:14 tempfile
Now all those flags.. -l -a -h
are such a pain to add.. It’s easier to chain them with just like this:
ls -lah
Works exactly the same, just easier to write
mcsneaky@bunter ~/guide
└─$ ls -lah
total 8.0K
drwxr-xr-x 2 mcsneaky mcsneaky 4.0K Aug 24 16:21 .
drwxr-xr-x 12 mcsneaky mcsneaky 4.0K Aug 24 15:17 ..
-rw-r--r-- 1 mcsneaky mcsneaky 0 Aug 24 16:21 .hidden
-rw-r--r-- 1 mcsneaky mcsneaky 0 Aug 24 15:14 tempfile
Piping |
One command I use quite a lot is checking out what’s listening on some certain TCP port
netstat -tulpn
But since it can give quite a long list of things running it’s a pain to find what’s listening on certain port. Like 1313
for example
then pipe + grep
comes handy
netstat -tulpn | grep 1313
mcsneaky@bunter ~/guide
└─$ netstat -tulpn | grep 1313
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
tcp 0 0 127.0.0.1:1313 0.0.0.0:* LISTEN 997/hugo
Nice! Now I know that it’s Hugo that’s listening for port 1313 and since I also know it’s PID I can kill it
kill 997
and BOOM! It’s dead
We’ll come back to this:
(Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all.)
IO and redirecting
- Standard input is
/dev/stdin
or/dev/fd/0
with file descriptor as0
, which defaults to keyboard - Standard output is
/dev/stdout
or/dev/fd/1
with FD of as1
, which defaults to screen - Standard error is
/dev/stderr
or/dev/fd/2
with FD of as.. You guess it2
, which defaults to screen too
Those are important to know when you want to mess with some stuff. Really good is to use FDs to get rid of error messages in outputs or to log errors into some file
Above we used netstat -tulpn | grep 1313
which threw some error about root.. I don’t care about this error, so I can just “hide it” (send it to /dev/null)
netstat -tulpn 2> /dev/null | grep 1313
mcsneaky@bunter ~/guide
└─$ netstat -tulpn 2> /dev/null | grep 1313
tcp 0 0 127.0.0.1:1313 0.0.0.0:* LISTEN 997/hugo
BOOM No error!
It’s quite stupid example, but you can do something similar with du -sh /etc/
which is prone to throw a lot of errors like du: cannot read directory '/etc/ssl/private': Permission denied
Can hide all those errors with redirecting standard error to /dev/null
How it works is quite simple. Every process accepts some inputs, does the processing and it writes results to output or error. You can define where those outputs go to tho.
You can also send them both to same file. Let’s have CRON job as an example
*/10 * * * * somecommand >> /cronlog.log 2>&1
It will run somecommand
once every 10 minutes
, will send standard error to standard output (2>&1
) and then will write both to /cronlog.log
.
Useful tricks
Some useful / handy tricks to make life lil bit easier
BANG BANG!!
Ever had a problem, that running rm -rf /
won’t execute, since need to run it with root permissions?
Easy problem is just to sudo bang!!
it
Oke actually don’t bang that, but moving some file won’t be too bad. For example let’s move our tempfile
to /srv/
(for whatever reason)
mv ./tmpfile /srv
mcsneaky@bunter ~/guide
└─$ mv tempfile /srv/
mv: cannot move 'tempfile' to '/srv/tempfile': Permission denied
And here comes the magic!
sudo !!
mcsneaky@bunter ~/guide
└─$ sudo !!
sudo mv tempfile /srv/
!!
refers to last executed command. Adding sudo
in front of it will execute last command again with elevated permissions
Bash native command “bookmarking”
Execute command and bookmark it:
mcsneaky@bunter ~/guide
└─$ cat /srv/tempfile #tempcontent
tempfile content
Execute command from history by bookmark
mcsneaky@bunter ~/guide
└─$ !?tempcontent
cat /srv/tempfile #tempcontent
tempfile content
!?
searches from git history by the end of command
Run the last certain command
# Run ls
mcsneaky@bunter ~/guide
└─$ ls -lah
total 8.0K
drwxr-xr-x 2 mcsneaky mcsneaky 4.0K Aug 24 21:38 .
drwxr-xr-x 12 mcsneaky mcsneaky 4.0K Aug 24 21:53 ..
-rw-r--r-- 1 mcsneaky mcsneaky 0 Aug 24 16:21 .hidden
# Run some random command
mcsneaky@bunter ~/guide
└─$ !?tempcontent
cat /srv/tempfile #tempcontent
tempfile content
# Run last `ls` command
mcsneaky@bunter ~/guide
└─$ !ls
ls -lah
total 8.0K
drwxr-xr-x 2 mcsneaky mcsneaky 4.0K Aug 24 21:38 .
drwxr-xr-x 12 mcsneaky mcsneaky 4.0K Aug 24 21:53 ..
-rw-r--r-- 1 mcsneaky mcsneaky 0 Aug 24 16:21 .hidden
Replace command but keep the arguments
In case you checked whats in /srv/ folder with ls
and now want to cd
to there
# Check what's in srv
mcsneaky@bunter ~/guide
└─$ ls /srv/
tempfile
# Move to checked location
mcsneaky@bunter ~/guide
└─$ cd !$
cd /srv/
mcsneaky@bunter /srv
└─$ |
Extra content
Show current git branch near current location
Add this to your ~/.bashrc
export PS1='\[\033[0;32m\]\[\033[0m\033[0;32m\]\u\[\033[0;36m\]@\[\033[0;36m\]\h \w\[\033[0;32m\]$(__git_ps1)\n\[\033[0;32m\]└─\[\033[0m\033[0;32m\]\$\[\033[0m\033[0;32m\]\[\033[0m\] '
Feel free to modify it however you like it more
Saving to read-only file in vim (save with sudo)
We all have ended up in situations where we open the file and edit it, but when trying to save then it gives “permission denied”…
Seems like forgot to open that Nginx config file with sudo vim
.. Can always close the editor and reopen it, but there’s a lot easier trick:
:w !sudo tee %
It consists onf multiple smaller things
-
:w
doesn’t actually write to file,:w
writes to buffer and by default it tries to write to same file -
tee
is a T shaped pipe, one pipe output is to file and other pipe output we can just ignore. Could also send it to /dev/null if it makes more sense (but it’s longer to write..):w !sudo tee > /dev/null %
-
%
stands for current file name -
!sudo
pipes the content of current buffer to another command with elevated permissions
Slightly laggy gif.. Had to fight cat stepping on keyboard :)
Will keep updating this post from time to time
1186 Words
2020-08-24 11:41 +0000