The script runs from command line but crontab fails

余生长醉 提交于 2020-01-11 11:32:16

问题


I'm still learning Bash and I'm having a problem with my script. I want to filter some calls with this script that is analyzing a call log, every 2 minutes as cronjob. The problem is that I can run it manually but it fails when run automatically from cron. I don't know why. It shouts something about permissions, so I kinda patched the script, so if it seems dirty I'm sorry.

#!/bin/bash

YESTERDAY=$((`date +'%s'`-86400))
AYER=`date -d "1970-01-01 $YESTERDAY sec" +"%Y%m%d"`
FECHA=`date +"%Y%m%d"`

FILENAME="$FECHA.log"
FILE_LINE="$FECHA.last"
FILE="/apps/sittel/rawdata/mitel.$FECHA"

# Limpiar carpeta tmp

if [ -e "tmp/$AYER.lnum" ]; then
    rm tmp/${AYER}.*
fi

# Si existe el archivo con el numero de laultima linea se procesa

if [ -e "tmp/$FECHA.lnum" ]; then

    # Se lee el numero de la linea y se extrae un archivo con las lineas apartir
    # de la ultima busqueda que se hizo, posteriormente se les hace un grep

    while read line
    do
            tail -n +$line $FILE > "tmp/$FECHA.hal"
    done < "tmp/$FECHA.lnum"
    cd tmp

    grep -n " 00[0|2-9][0-9]\{4,\}" "tmp/$FECHA.hal" > "tmp/${FECHA}.new"

    grep -n " 900[0|2-9][0-9]\{4,\}" "tmp/$FECHA.hal" >> "tmp/${FECHA}.new"

    cd ..
    echo `pwd`
    cat tmp/${FECHA}.new >> logs/$FILENAME

else
    # Este caso es la primera vez que se ejecuta, verifica si el log ya existe
    # de ser asi, lo elimina para evitar duplicados

    if [ -e "logs/$FILENAME" ]; then
            rm "logs/$FILENAME"
    fi

    # Se realiza un grep en el archivo indicado y se marca el archivo de salida
    # se busca todos los numeros k empiecen con 00 seguidos de 0 a 9 execpto el 1

    cd tmp

    grep -n " 00[0|2-9][0-9]\{4,\}" $FILE>"${FECHA}.new"

    grep -n " 900[0|2-9][0-9]\{4,\}" $FILE>>"${FECHA}.new"

    cat ${FECHA}.new >> $FILENAME

    mv $FILENAME ../logs

    cd ..
fi

    cp "tmp/${FECHA}.new" "tmp/message.txt"

    echo "Mensaje" | mail -s "$SUBJECT" "$EMAIL" < "tmp/message.txt"

fi

if [ -e "tmp/${FECHA}.new" ]; then
    rm "tmp/${FECHA}.new"
fi

tail -n1 "logs/$FILENAME" > "tmp/$FILE_LINE"   

IFS=$':'
while read line
do
    DATOS=($line)
    LINE_NUMBER=${DATOS[0]}   
    echo $LINE_NUMBER > "tmp/$FECHA.lnum"
done < "tmp/$FILE_LINE"
unset IFS

and this is what the system prints:

/apps/sittel/Alarma/callAlarm: line 56: cd: tmp: No such file or directory
mv: cannot move `20110712.log' to `../logs': Permission denied
/apps/sittel/Alarma/callAlarm: line 69: tmp/20110712.last: No such file or directory
/apps/sittel/Alarma/callAlarm: line 77: tmp/20110712.last: No such file or directory

回答1:


Your script assumes that it is being run from a particular directory (note that almost every path is a relative path, not an absolute path). cron happens to be running it from another directory.

The Fix

If the script works when you run it from the directory it lives in, add the following to the top of your script:

mydir=$(dirname "$0") && cd "${mydir}" || exit 1

Explanation

$0 is the (possibly relative) filename of the shell script being executed. Given a filename, the dirname command returns the directory containing the filename.

So, that line changes directories to the directory containing the script or exits with an error code if either dirname or cd fails.




回答2:


Looks like you may need to cd into the correct directory at the start of your script.

Put a pwd at the beginning, followed by exit and watch the cron output to see where you're executing from. There's also a chance that you have a shorter PATH when running under cron, but it should still have access to tail and grep.




回答3:


It seems that you are assuming a certain starting directory, and creating a tmp directory there. But when you run it as a cron job, it starts in a different place. So a CD command in your bash startup script might mess you up. You can easily test by using the full path names when you cd or rm or whatever.

For example,

if [ -e "tmp/$AYER.lnum" ]; then
    rm /home/username/tmp/${AYER}.*
fi

# Si existe el archivo con el numero de laultima linea se procesa

if [ -e "/home/username/tmp/$FECHA.lnum" ]; then

    # Se lee el numero de la linea y se extrae un archivo con las lineas apartir
    # de la ultima busqueda que se hizo, posteriormente se les hace un grep

    while read line
    do
            tail -n +$line $FILE > "/home/username/tmp/$FECHA.hal"
    done < "/home/username/tmp/$FECHA.lnum"
    cd /home/username/tmp

    grep -n " 00[0|2-9][0-9]\{4,\}" "/home/username/tmp/$FECHA.hal" > "/home/username/tmp/${FECHA}.new"

and so on.



来源:https://stackoverflow.com/questions/6668588/the-script-runs-from-command-line-but-crontab-fails

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!