Bash Script Fails *Only* from Cron with “Not a Valid Identifier”

I have a script that creates a new log file each week that can be called from other scripts with a log file parameter. Without any arguments it creates a log with the name of the parent process in ~/bin/log. This works fine in a terminal, but in a cron job it fails complaining that the function default-log is “not a valid identifier”.

The function seems trivial and everything it does works fine outside the function. I can easily work around this as the function is only called twice and I can just substitute the whole 2 lines, but I’d still like to understand what’s going on.

Other details:

  • Not a root cron job
  • The cron job is actually a script that calls this (weekly-log "$LOG") but all the echoed paths, etc. in my debugging look fine
  • Tested using “Run selected task” in gnome-schedule. This seems to produce the same environment, but you get to see the output.
  • Ubuntu 16.04

#!/bin/bash
#
# Start fresh logfile each Monday using the supplied path/name
# or create in ~/bin/logs with the name of the calling script

LOG=""
PARENT="$(ps -o comm= $PPID)"
DATEFORMAT="+%a %e %b %Y %I:%M:%S %P %Z"
# Thu 26 Jan 2017 01:52:49 pm AEDT

# Debugging—these all look OK
echo "Args: $*"
echo "PPID: $PPID"
echo "PARENT: $PARENT"
echo "HOME: $HOME"
echo "Default LOG: $HOME/bin/log/$(basename "$PARENT").log"
mkdir -p "$HOME/bin/log"

function default-log {
  mkdir -p "$HOME/bin/log"
  LOG="$HOME/bin/log/$(basename "$PARENT").log"
}

if [ $# -eq 0 ] ; then
   echo "No args"
   default-log
#   mkdir -p "$HOME/bin/log"
#   LOG="$HOME/bin/log/$(basename "$PARENT").log"
else
  DIR=$(dirname "$1")
  # dirname returns "." for invalid path!
  if [ ! "$DIR" = "." ] && [ -d "$DIR" ] ; then
    LOG="$1"
  else
    echo "Invalid path"
    default-log
#    mkdir -p "$HOME/bin/log"
#    LOG="$HOME/bin/log/$(basename "$PARENT").log"
    echo "Invalid path to log file: $1" 2>&1 | tee "$LOG"
  fi
fi

# Create new log or append
if [[ $(date +%u) -eq 1 ]] ; then
  echo "--------------------------------" 2>&1 | tee "$LOG"
else
  echo 2>&1 | tee -a "$LOG"
  echo "--------------------------------" 2>&1 | tee -a "$LOG"
fi
echo $(date "$DATEFORMAT") 2>&1 | tee -a "$LOG"
echo "" 2>&1 | tee -a "$LOG"
2

1 Answer

According to POSIX, function names can contain only word characters ([a-zA-Z0-9_]) (source: part 1, part 2). Change the function name from default-log to default_log.

But, Bash is normally very lenient about function names, so I'm not sure why it's failing.

0

Your Answer

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

Marcus Vance

Marcus Vance

Cybersecurity & Digital Privacy Researcher

Marcus Vance is a cybersecurity auditor and technology writer dedicated to educating the public about online safety, data privacy regulations, enterprise security, and emerging cyber threats.

Share this article
Twitter Facebook Pinterest