CategoryBash

Completely wipe Bash history

Clearing out your bash history can be quite a hassle as it keeps a copy in the memory that will be flushed at the moment you log out. There is a workaround:

cat /dev/null > ~/.bash_history && history -c && exit

After this command the history is wiped.
I use this when creating binary copies of the filesystem when I do not want to include any history (Create bitwise copy of EMMC/SD/HDD/SDD over the network (backup using ssh pipe)).

Source: https://askubuntu.com/a/192001

Create bitwise copy of EMMC/SD/HDD/SDD over the network (backup using ssh pipe)

It can be convenient to make a bitwise copy. For example to place the contents of 1 embedded board (i.e. Beaglebone) to another embedded board.

If the device to copy is also the storage device that holds the OS, then boot from another device, for example a “Try Ubuntu” usb drive.

We stream the data over the network, because the devices themselves mostly have no space to place the image somewhere on the that device.

Assumption is that you have a working ssh server on the device you want to copy to.

The perform the following:

  1. Find the correct device to make a copy from. So the whole device, not the partition.
    In my case it is “/dev/mmcblk0” so without the partition indicator -> “p1”.
  2. Find the ip adress of the device to copy to (or use hostname)

To create an image:

> sudo cat /dev/mmcblk0 | ssh <user>@<ip-adress> "gzip ~/image.gz"

After the operation is done you have a bitwise copy gzipped on your <ip-address> machine in the home directory of the <user>

To deploy an earlier created image back to the device, from the device to deploy to (Make sure you booted from another device than we are copying to):

> ssh <user>@<ip-address> "gzip -dc ~/image.gz" | dd of=/dev/mmcblk0 status=progress

Wipe bash history!

If you were ever to create an image of your OS for example, but do not want to include your history.

It also wipes the history still in the memory.

cat /dev/null > ~/.bash_history && history -c && exit

Also, if you don’t even want that your command ends up in your bash history in the first place, add a space at the start of you command and it will not be in your bash history!

> echo "inhistory" > blaa
>   echo "notinhistory" > blaa  #notice the space

The “notinhistory” is not in the history file:

> history | tail -n1
10438  echo "inhistory" > blaa

Bash script template

Whenever writing a script you might want to enable some options depending on what you provide on the CLI.

I’ve created a bash script template to getting started quick with a bash script. You can specify full options or the short ones with arguments or without.

#!/bin/bash
# Version 2.0
# Script template

set -eou pipefail

DO_OPT_A=false
DO_OPT_B=false

# directory of the script, can be useful for locating files which are next to the script.
THISDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"

function main() {
  check_root

  do_parse_opts $@

  [[ ${DO_OPT_A}   = true ]] && check_opt_a_prerequisites
  [[ ${DO_OPT_B}   = true ]] && check_opt_b_prerequisites

  print_info "Checks OK, you have 2s to abort now!"
  sleep 2
  echo ""

  [[ ${DO_OPT_A} = true ]] && {
    do_opt_a_function
  }

  [[ ${DO_OPT_B} = true ]] && {
    do_opt_b_function
  }
}

function show_help() {
  echo "Scripting template :)"

  echo "Usage:"
  echo "    $0 [-a/--option_a] [-b/--option_b <arg>]"

  echo "        *  [-h/--help]      Print this help"
  echo "        *  [-a/--option_a]  Perform option A"
  echo "        *  [-b/--option_b <arg>]  Perform option B with argument"
  echo ""
  exit 1
}

function do_parse_opts() {
  # convert long options to shorts
  for arg in "$@"; do
    shift
    case "$arg" in
        "--help")       set -- "$@" "-h" ;;
        "--option_a")   set -- "$@" "-a" ;;
        "--option_b")   set -- "$@" "-b" ;;
        *)              set -- "$@" "$arg"
    esac
  done

  OPTIND=1 # Reset in case getopts has been used previously in the shell.
  while getopts "hab:" opt; do
      case "$opt" in
      h)
          show_help
          exit 0
          ;;
      a)  DO_OPT_A=true
          ;;
      b)  DO_OPT_B=true
          BARG=$OPTARG
          ;;
      esac
  done

  shift $((OPTIND-1))

  [ "${1:-}" = "--" ] && shift

  print_info "DO_OPT_A    = $DO_OPT_A"
  print_info "DO_OPT_B    = $DO_OPT_B"

  [[ ${DO_OPT_A} = false ]] && [[ ${DO_OPT_B} = false ]] && {
    print_info "Hey! Your provided no options, this might help:"
    echo ""
    show_help
  }

  echo ""
}

function check_root() {
    [[ $EUID -ne 0 ]] && {
        echo "[ERROR]     This script must be run as root"
        show_help
    }
}

function check_opt_a_prerequisites() {
    print_info "Checking option A prerequisites"
    sleep 1
    print_ok
}

function check_opt_b_prerequisites() {
    print_info "Checking option B prerequisites"
    sleep 1
    print_ok
}


function do_opt_a_function() {
    print_info "Performing A"
    sleep 1
    print_ok
}


function do_opt_b_function() {
    print_info "Performing B, with arg: ${BARG}"
    sleep 1
    print_ok
}


function print_ok() {
  echo "[OK]"
}

function print_info() {
  echo "[INFO]      $1..."
}

function print_error() {
  echo "[ERROR]     $1"
  exit 1
}


main $@

print_info "All done!"
echo "[OK]"

Git status of multiple git repositories in one directory

If a project consists of multiple git repositories I’d like to see if I forgot to create a commit in one of them at the end of a development day.

This little bash script traverses all directories with a .git directory and checks with a ‘git status’ what the status of that git repository is.

Handy! I’d use it, if it were me!

for x in $(find . -type d -name ".git"); do pushd $(dirname $x); pwd; git status; popd; done

Increasing RAM with SWAP partition

When building large projects with Yocto/Bitbake I encountered hangups of my host OS due to lack of RAM space.

The solution to that was creating a SWAP partition, which actually allocates space on a SSD (preferably) or a HDD. Note that a HDD and SSD are always slower than RAM, but better than having hangups.

How to create a swapfile on Ubuntu 18.04 (may work on other distros as well). Replace <user> with your local user (echo $USER).

  1. Create a swap file with dd. I generally double my RAM capacity, so I choose my swapfile to be the same size as RAM on my system.
# bs=1G and count=4 -> 4GB swapfile
$ dd if=/dev/zero of=/home/<user>/swapfile bs=1G count=4

2. Set correct permission on the swapfile

$ sudo chmod 600 /home/<user>/swapfile

3. Make ‘swapfile’ usable as swap

$ sudo mkswap /home/<user>/swapfile

4. Tell the OS to use the swapfile

$ sudo swapon /home/<user>/swapfile

In principle you are done. The OS is using your swapfile. However it is not acitivated on a restart of your OS. To fix that we have to add it to the fstab file.

5. Add the following line to the /etc/fstab

/home/<user>/swapfile none swap sw 0 0

Check with “top”, “htop”, or even “bashtop” your new physical memory size!

Finally, you’d like not to use the swapfile if it is not necessary. You can specify the “swappiness” for that.

# 0 = disable swap, 100 = swap as much as possible
$ sysctl vm.swappiness=10

Sources:
[1] https://help.ubuntu.com/community/SwapFaq

Get notified on a SSH login

Of course nobody should be able to login to your server. But if someone finds a way to do it, don’t you want to know it?

I am running an Ubuntu Server that uses motd to welcome logged in users. Therefore I am using motd to execute a script for me once a user logged in.

I extracted the details of the just logged in user from /var/log/auth.log, and uses the IP address and a resolver (ipapi.co in my case) to resolve the IP address to a location.

I am using a Telegram Chat with my own Telegram bot to notify me. I might write a small blogpost about my Telegram bot in the future.

Place the script in a file, make it executable, and place it in /etc/update-motd.d/. For example:

$ touch /etc/update-motd/01-notify-me.sh
$ chmod +x /etc/update-motd/01-notify-me.sh
$ vi /etc/update-motd/01-notify-me.sh # Add script 

And the actual script:

#!/bin/bash

_loginDetails=$(grep "Accepted" /var/log/auth.log | tail -n 1)
_IP=$(echo $_loginDetails | awk '{print $11}')
_LOCATION=$(curl https://ipapi.co/${_IP}/json/ | jq .city -r)
_METHOD=$(echo $_loginDetails | awk '{print $7}')
_WHO=$(echo $_loginDetails | awk '{print $4}')
message="[SSH LOGIN] => ${_WHO} from ${_LOCATION}, IP: ${_IP}, AUTH: ${_METHOD}"

curl -s -X POST https://api.telegram.org/<bot_token>/sendMessage -d chat_id=<chat_id> -d text="${message}"

Additional security measures should be taken, for example:

  • Login with Key only
  • Disallow root login via ssh
  • Blacklist IP’s
  • Block based on Geo location
  • fail2ban

© 2025 Roholt

Thema door Anders NorénOmhoog ↑