cron: sintaxe bash não funciona

1

Estou tentando adicionar o seguinte comando ao crontab:

I=1; for X in $(/bin/ls -r /var/tmp/*); do [ $((I++)) -le 28 ] && echo "lower" || echo "higher"; done

Quando executado na linha de comando (no bash), o comando funciona bem. Mas quando eu adiciono a linha no crontab e quando executado, o cron reclama:

/bin/sh: 1: arithmetic expression: expecting primary: "I++"

Eu preciso usar uma sintaxe diferente no cron?

EDIT1: Eu substituí sh por bash em meu /etc/crontab :

SHELL=/bin/bash

Reiniciei cron , mas a linha cron ainda não foi executada:

(I=1; for X in $(/bin/ls -r /var/tmp/*); do [ $((I++)) -le 28 ] && echo "lower" || echo "higher"; done)

o erro sugere que ainda está sendo interpretado com /bin/sh em vez de /bin/bash :

/bin/sh: 1: arithmetic expression: expecting primary: "I++"
    
por Martin Vegter 29.09.2013 / 21:19

3 respostas

3

Cron, se não me engano, padrão para /bin/sh . Verifique /etc/crontab/ para a linha SHELL= . É provável que seja definido como /bin/sh ( dash ). Acredito que você pode definir SHELL=/bin/bash em seu próprio arquivo crontab de usuário (aquele editado por crontab -e ). Ou você pode fazer o script.

    
por 29.09.2013 / 21:29
3

Sim, você precisa usar a sintaxe sh . Você pode encontrar a especificação para o padrão portátil sh sintaxe .

Nesse caso, você deseja [ "$((i+=1))" -le 29 ] , ou se seu sh for baseado em uma versão antiga de ash que ainda não suportava o conjunto completo de operadores aritméticos padrão, use [ "$i" -le 28 ] ...; i=$(($i + 1)) .

Uma nota de aviso: processar um diretório gravável do mundo como /var/tmp sob cron é como abrir uma lata de segurança worm.

Você precisa tratar os nomes dos arquivos e o tipo deles como não confiáveis e extremamente sujos.

Seu $(/bin/ls -r /var/tmp/*) em particular é falso, pois faz muitas suposições sobre quais caracteres os nomes de arquivos podem conter e supõe que nenhum deles são diretórios ou links simbólicos para diretórios.

    
por 29.09.2013 / 21:27
2

Para tornar isso totalmente portátil, você pode substituir a sintaxe $ () por:

I=1; for X in '/bin/ls -r /var/tmp/*'; do [ $I -le 28 ] && echo "lower" || echo "higher"; I='expr $I + 1'; done

Mas cuidado com agendamentos cronológicos e diretórios graváveis mundiais.

    
por 30.09.2013 / 01:27

Tags