0

I have a cron job that keeps spawning child process with the same name as parent process every few seconds. All the CPU usage is happening on the child process for few seconds and then dies. Seems really strange. Here is output of htop:

CPU% MEM%  Command
0         0            /bin/sh -c /etc/script.sh > /var/log/script.log
0         0                |— /bin/bash /etc/script.sh
100     0.4                   |— /bin/bash /etc/script.sh

The last process keeps respawning every few seconds. Why does it not run under one process? Should the child process commands be more like the actual commands I run from script like: |-- find .. / or / |-- grep or |-- tar ?

Cron:

*/30 *   *   *   *   root  /etc/script.sh > /var/log/script.log

Script:

    #!/bin/bash

    LOG_DIR={{ log_dir | default('/var/logs') }}
    ARCHIVE_DIR={{ archive_dir | default('/var/archive') }}
    PIDFILE={{ pidfile | default('/run/script.pid') }}

    ## Handle cases where cronjobs take too long to prevent starting new ones
    if [ -f $PIDFILE ]
    then
        PID=$(cat $PIDFILE)
        ps -p $PID > /dev/null 2>&1
        if [ $? -eq 0 ]
        then
            echo "Process already running"
            exit 1
        else
            ## Process not found assume not running
            echo $$ > $PIDFILE
            if [ $? -ne 0 ]
            then
                echo "Could not create PID file"
                exit 1
            fi
        fi
    else
        echo $$ > $PIDFILE
        if [ $? -ne 0 ]
        then
            echo "Could not create PID file"
            exit 1
        fi
    fi


    new_files_archived=0
    for folder in $(ls ${LOG_DIR});
        do
            ## Archive the last 30 days worth of logs
            log_files=$(find -H ${LOG_DIR}/${folder} -not -empty -type f -regex '.*.log' -mtime -5)
            archived_logs_files=$(find ${ARCHIVE_DIR/$folder} -type f)
            if [ $? -eq 0 ]; then
                mkdir -p "$ARCHIVE_DIR/$folder"
            fi
            for log_file in $log_files;
                do
                    grep -q $(basename ${log_file} .log) <<<$archived_logs_files
                    if [ $? -eq 0 ]; then
                        :
                        #echo $log_file Found, already archived, skipping..
                    else
                        echo ${log_file}.gz Not Found, creating archive
                        gzip -c $log_file > "$ARCHIVE_DIR/$folder/$(basename ${log_file}).gz"
                        touch -d "$(date -R -r ${log_file})" "$ARCHIVE_DIR/$folder/$(basename ${log_file}).gz"
                        let new_files_archived++
                    fi
            done;
    done;
    echo $new_files_archived new files added to archive

    ## Remove file lock after executing
    rm $PIDFILE
1
  • 1
    Not really your issue... but have you considered using logrotate instead of your script? – jordanm Nov 18 '19 at 22:41
0

Is the script file marked as executable ie 'x' ? Which is the owner ? root or your normal user ?

I personally prefer to qualify commands ie provide a complete path to for example find so :

LOG_FILES=$(/bin/find -H ${LOG_DIR}/${folder} -not -empty -type f -name '*.log' -mtime -5)

use name instead of regex because regex in this case doesn't provide any more functionality. Especially because regex '.' match will match any character so it will match 'helloslog' which you probably dont want.

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.