Safer Bash Scripting Tips

Safer Bash Scripting Tips

I hope you are all well and safe. As "stay safe" is the most used expression during this COVID-19 period, I thought it would be nice to extend safety to other areas as well. How about we talk about some simple tips to make your Bash scripts safer and even more robust?

Imagine you have an application that keeps reading from a directory with a lot of small static files. We're talking about file reading operations. Let's call this directory "/var/appX/data". The program appX makes constant read operations to gather data from that directory. Now, imagine that part of that data has changed and you need to update just one parameter inside all the static files that have the ".prm" extension (I've just invented that! :P).

As a good "shell scriptor" you start thinking right away about a for loop and some cryptic REGEX feeding a sed command, right? Cool! The solution is simple, but there might be something under the hood you didn't see at first! What if your script crashes (for some reason), or gets killed by someone else who has the privileges for doing that (who knows) ?

Your appX will start yelling at you and write very nasty things inside its log files, as part of the information it is gathering will be correct, and part will be miserably wrong!

How to solve that? Try to be atomic!

In short, being atomic means to do the operation in one single tick! How could you be atomic in this scenario? Well, use commands that perform that way! The mv and mkdir are examples of commands that perform atomic operation, because the operating system needs to be sure that things will be done in one single tick!

Let's see that in action. First, imagine the reckless (snippet) version of your script.

#!/bin/bash


# Saves current IFS
CUR_IFS=$IFS
IFS=$(echo -en "\n\b")


DATA_DIR="/var/appX/data"


for file in $(find "$DATA_DIR" -name "*.prm")
do
    sed -i 's/OLD_PARAM/NEW_PARAM/g' "$file"
done

Do you see the mess being setup? All the tears, blood and suffering that will rise from that script being killed in action?

Now, if a little modification, appX and people are going to be happy forever after.

#!/bin/bash


# Saves current IFS
CUR_IFS=$IFS
IFS=$(echo -en "\n\b")


DATA_DIR="/var/appX/data/"
DATA_DIR_TMP="$(echo "${DATA_DIR%%/*}_tmp"
DATA_DIR_OLD="$(echo "${DATA_DIR%%/*}_old"

cp -a "$DATA_DIR" "$DATA_DIR_TMP"

for file in $(find "$DATA_DIR_TMP" -name "*.prm")
do
    sed -i 's/OLD_PARAM/NEW_PARAM/g' "$file"
done

# Now, be atomic!
mv "$DATA_DIR" "$DATA_DIR_OLD"
mv "$DATA_DIR_TMP" "$DATA_DIR"

What have we done? Well, we just created a copy from the original data to be modified and performed the alterations on that copy. After that, we just moved the current data directory to an old one and then moved our copy to be the main one. For this to be effective, you should consider that all these copy and moving operations are done within the same partition, because in that case moving data will be just a matter of updating the inodes table within the files system. In addition, if that script was killed in action, you'd have to worry only about repeating its execution and be sure it would finish its tasks.

I hope you liked this one. If the idea behind this is clear to you, you'll definitely adapt this concept to other scenarios as well.

Happy scripting.

--FIN--


Gabriel M.

Linux Systems Engineer | IT Infrastructure | Security | Virtualization | Automation | AI | C and Shell Scripting

4 年

Cleir, meu caro, sempre curtindo meus artigos. Obrigado! :)

回复

要查看或添加评论,请登录

Gabriel M.的更多文章

  • Docker 101

    Docker 101

    A (tiny) introduction to Docker. If you want to get your hands dirty with some Docker content, this quick introduction…

  • Building custom kernels for Linux + updating the system firmware.

    Building custom kernels for Linux + updating the system firmware.

    In this post I'll show you how you can replace your current Linux kernel with a new one built entirely from the…

  • Debian complained about missing firmware during installation? Add missing 'non-free' firmware to installation image! :)

    Debian complained about missing firmware during installation? Add missing 'non-free' firmware to installation image! :)

    If you have installed Debian, you might have faced the screen below: And probably got very frustrated, because your…

  • Using Traps in Bash Scripts

    Using Traps in Bash Scripts

    Imagine that you have a script to perform some critical operation, one that would render the system completely unusable…

    2 条评论
  • Pointers and 2D-arrays in C

    Pointers and 2D-arrays in C

    When taking the Engineering or CS undergrad path, like 1+1 leads to 2 (let's keep it simple here, shall we?), students…

    2 条评论
  • Linux Kernel Inotify Subsystem

    Linux Kernel Inotify Subsystem

    When dealing with Unix-style filesystems there must be a data structure that is capable of describing an object from…

  • Linux File I/O

    Linux File I/O

    When using system calls for dealing with file I/O, open(), read(), write() and close() are the four functions used to…

  • Shifting bits in C

    Shifting bits in C

    Have you ever asked yourself how much memory space do you waste when writing your code? Sometimes you just need a…

  • Improving your Linux box security

    Improving your Linux box security

    Did you know that more than never, during these quarantine days, there is a lot more malicious activities undergoing…

  • Build UnrealEngine on Linux, making it use less disk space! :)

    Build UnrealEngine on Linux, making it use less disk space! :)

    If you are playing with the amazing Unreal Engine on your Linux box, you might have noticed that the final size after…

社区洞察

其他会员也浏览了