Automatic File Backups in VIM
Having to undo stupid changes to config files is an unfortunate side effect of too few sysadmins supporting too many servers. The VIM editor has some built-in file backup options. However, I find these options very limited and generally not particularly well suited to sysadmin work.
A solution has been around for decades (for vi
and other CLI editors), and it’s a wrapper script. Here’s my version, and I tried to keep it simple. You can download the script from my GitHub repo or copy it below. Make it executable and add a link – say, /usr/bin/vish
.
#!/bin/bash declare -a a an i=0 for f in "${@}" do if [ -f "${f}" ] then fn="$(dirname "${f}")/$(basename -- "${f%.*}")_$(date -d @$(stat -c %Y "${f}") +'%Y-%m-%d_%H%M%S')@$(date +'%Y-%m-%d_%H%M%S')$([[ "${f}" = *.* ]] && echo ".${f##*.}" || echo '')" a+=("${f}") an+=("${fn}") /bin/cp -p "${a[$i]}" "${an[$i]}" (( i = i + 1 )) fi done vim "${@}" if [ $? -eq 0 ]; then for ((i = 0; i < ${#a[@]}; i++)) do if cmp -s "${a[$i]}" "${an[$i]}" then /bin/rm -f "${an[$i]}" 2>/dev/null fi done fi
It will help if you run it the same way you would run the vim
command by providing one or more filenames you wish to edit. The path to the files can be either absolute or relative. For example:
vish /etc/hosts /etc/resolv.conf # or cd /etc && vish hosts resolv.conf
The backup files are created when you run the wrapper script. When you exit VIM, the script will compare current versions of the files you edited to the backups it created earlier. If there was no change, the unneeded backups will be removed. Now, if you check the /etc
folder, you will see the two new backup files:
ls -als /etc | egrep "hosts|resolv" 4 -rw-r--r-- 1 root root 1775 Aug 17 10:08 hosts 4 -rw-r--r-- 1 root root 1775 Aug 17 10:08 hosts_2021-08-17_100812@2021-08-17_113833 0 -rw-r--r-- 1 root root 192 Aug 16 18:44 resolv_2020-10-28_005723@2021-08-17_113833.conf 0 drwxr-xr-x 1 root root 4096 Oct 28 2020 resolvconf 0 lrwxrwxrwx 1 root root 29 Oct 28 2020 resolv.conf -> ../run/resolvconf/resolv.conf
The backup filename format goes something like this:
<original_filename_without_extension>_<original_timestamp>@<current_timestamp>.<original_extension>
This tells me when the file was last modified and its previous modification date – both can be critical pieces of information when trying to figure out why something stopped working.