1

I'm using this bash script to maintain 3 backups of my server. For some reason, it randomly creates an empty file with the name of one of my variables. The variable name it chooses is seemingly random, and it doesn't create the file every single time that it's run.

I'm running Ubuntu Server 16.04LTS

The script works perfectly as intended. I'm just wondering why bash creates the file sometimes.

NOTE: I have omitted some sensitive information such as the Samba address, and location of the CIFS credentials. This was intentional and is correct in my actual script.

I'm running this script from a cron job with the command bash backup.bash, so bash is explicitly used to run the script

#!/bin/bash

## The number of backups that we want to keep
MAX_BACKUPS=3

## The directory to store the backups
BACKUP_DIR="OMITTED"

## The address of the Samba Share
REMOTE_ADDR="OMITTED"

## What we want to name the backup
BACKUP_NAME="$(date +"%m_%d_%Y")_backup.tar.gz"

## Mount the Samba Share to the backup directory
mount -t cifs -o credentials=OMITTED,noperm $REMOTE_ADDR $BACKUP_DIR

## Make todays backup
tar -cpzvf $BACKUP_DIR/$BACKUP_NAME --exclude-from=/backup_scripts/backup.exclude /

## The number of backups that we now have
COUNT="$(find $BACKUP_DIR -maxdepth 1 -type f -name '*_backup.tar.gz' | wc -l )"

## If we have more backups than MAX_BACKUPS
if ((COUNT > MAX_BACKUPS)); then
  ## Delete the oldest file (DETERMINED BY MODIFICATION DATE)
  cd $BACKUP_DIR
  rm "$(ls -t | tail -1)"
fi

# Unmount the Samba Share for safety
umount $BACKUP_DIR
  • 5
    It probably won't fix anything, but you should quote your variables – Fox Dec 16 '17 at 15:27
  • 3
    How exactly does the name of the "empty file with the name of one of my variables" look? Which of your script variables would contain this name? Please provide some examples. Additionally, what on the first view strikes me as odd is the nested quoting when creating BACKUP_NAME, a thing I would try to avoid in my scripts. Another best practice is to enclose shell variables into curly brackets to avoid ambiguities: ${BACKUP_NAME}. – Murphy Dec 16 '17 at 15:37
  • 3
    what happens when the script is logged with -x to show what is going on? – thrig Dec 16 '17 at 15:41
  • 2
    In what directory do the files appear? It may also help to specifically list which variables are appearing -- is it every variable you use in the script? – mattdm Dec 16 '17 at 15:46
  • 6
    I can imagine ((COUNT > MAX_BACKUPS)) creating a file called MAX_BACKUPS if accidentally executed with a non-bash shell – steeldriver Dec 16 '17 at 16:23
2

Edit: as @StéphaneChazelas pointed out, the problem is likely that your script isn't being invoked with bash, and the (( )) construct won't work. Try running it from a bash shell or with bash my_script.sh

Also, that rm has the potential to fail spectacularly. Please read this FAQ.

  • 1
    The problem is not with not expanding $COUNT. ((COUNT > MAX_BACKUPS)) is correct in ksh/bash/zsh. Most likely, the script is not being interpreted by any of those shells here, maybe because it's run as sh the-script or . the-script from within a sh script. And then ((COUNT > MAX_BACKUPS)) is interpreted as a nested subshell, like in ( (COUNT > MAX_BACKUPS ) ) instead of an arithmetic expression. – Stéphane Chazelas Dec 18 '17 at 20:47
  • Thanks. So, does POSIX only have $(( ))? If so, would you have to use [ ] and -gt style operators for comparison? – m0dular Dec 18 '17 at 21:07
  • 1
    Yes, or [ "$((COUNT > MAX_BACKUPS))" -ne 0 ] for instance. Though [ "$COUNT" -gt "$MAX" ] would be more canonical (and would also be portable to the Bourne shell would you ever come across very old systems) – Stéphane Chazelas Dec 18 '17 at 21:14
  • I'm running it via a CRON job and the command I'm using explicitly calls bash. bash backup.bash – Native Coder Dec 19 '17 at 5:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.