Search code examples
linuxbashsedredhat

Using sed to replace text with slashes in crontab files


I'm trying to replace an entry in Crontab (RedHat) with sign #. I tried sed command like this

sed -i 's|35 15 * * * /tmp/vii/test.sh >/dev/null 2>&1|#|g' /var/spool/cron/root

but it doesn't work. Any ideas?


Solution

  • Server file edition is a bad practice!

    Don't try to edit crontab files directly, use crontab tools instead!!

    Simple sed way

    You could use:

    crontab -l
    

    to dump actual crontab list.

    crontab -l | sed '/vii.test.sh/s/^/# /'
    

    ... or more finely:

    crontab -l | sed '/^35 \+15.*vii.test.sh/s/^/# /'
    

    to pre-edit crontab list and see on terminal sed command result

    Then:

    crontab -l | sed '/vii.test.sh/s/^/# /' | crontab
    

    to replace actual crontab list, once everything are ok.

    But warn!

    wrong Command | crontab
    

    will erase completely your crontab list!!

    Scripted, line number based method

    There is a little script:

    #!/bin/sh
    
    SED=`which sed`
    CAT=`which cat`
    CRONTAB=`which crontab`
    
    lines=`$CRONTAB -l | wc -l`
    
    $CRONTAB -l |
        $CAT -n
    
    read -p 'Switch comment on line: ' line
    
    if [ -n "$line" ] && [ $line -ge 1 ] && [ $lines -ge $line ]; then
    
        $CRONTAB -l |
        $SED $line'{ s/^# //;t;s/^/# /;: }'
    
        read -p 'Apply this? (y/[n])' apply
        [ "$apply" = "y" ] &&
        $CRONTAB -l |
            $SED $line'{ s/^# //;t;s/^/# /;: }' |
            $CRONTAB
    
    fi
    

    May produce:

         1  # For more information see the manual pages of crontab(5) and cron(8)
         2  #
         3  # m h  dom mon dow   command
         4  00  4    *   *   *   /path/to/another/command
         5  35 15 * * * /tmp/vii/test.sh >/dev/null 2>&1
    Switch comment on line: 
    

    From there, if you hit 5 (followed by return):

    # For more information see the manual pages of crontab(5) and cron(8)
    #
    # m h  dom mon dow   command
    00  4    *   *   *   /path/to/another/command
    # 35 15 * * * /tmp/vii/test.sh >/dev/null 2>&1
    Apply this? (y/[n])n
    

    And you could press y if you're ok.

    For users:

    #!/bin/bash
    
    mapfile -t cronTab < <(crontab -l)
    
    paste <(seq 1 ${#cronTab[@]}) <(printf "%s\n" "${cronTab[@]}")
    
    read -p "Switch comment on line: (1-${#cronTab[@]}) " line
    
    (( (line>0) && (${#cronTab[@]}>=line) )) && { 
    
        [ "${cronTab[line-1]:0:1}" = "#" ] &&
        cronTab[line-1]="${cronTab[line-1]:2}" ||
        cronTab[line-1]="# ${cronTab[line-1]}"
    
        printf "%s\n" "${cronTab[@]}"
        read -p 'Apply this? (y/[n])' apply
    
        [ "$apply" = "y" ] &&
        printf "%s\n" "${cronTab[@]}" |
            crontab
    }