为什么这个cronjob不起作用?

目前正在尝试使用python脚本设置一个cron job ,我从这里克隆了git。 到达我的脚本的层次结构可以描述如下:

  /home | | /Daily-Reddit-Wallpaper | | change_wallpaper_reddit.py 

现在,当我在python change_wallpaper_reddit.py --time new文件夹中使用命令python change_wallpaper_reddit.py --time new时,这个工作正常。 但是,当我尝试命令时, * * * * * python ./change_wallpaper_reddit.py --time new ,我得到错误:

 change_wallpaper_reddit.py: command not found 

当我尝试调用* * * * * python ~/Daily-Reddit-Wallpaper/change_wallpaper_reddit.py ,我得到:

 usage: anaconda [-h] [--show-traceback] [--hide-traceback] [-v] [-q] [--color] [--no-color] [-V] [-t TOKEN] [-s SITE] ... anaconda: error: argument : invalid choice: 'Daily-Reddit-Wallpaper' (choose from 'auth', u'label', u'channel', 'config', u'copy', u'download', 'groups', u'login', 'logout', u'notebook', 'package', 'remove', 'search', 'show', u'upload', u'whoami') 

我不明白为什么会这样。

问题是,该脚本不适用于Cron。 它使用很少的环境变量,这些变量无法从Cron访问,它们是不同的,具体取决于当前用户的桌面环境。 这就是其页面上描述另一种在启动时运行的方式的原因。 但是可以在CronJob运行时设置这些变量的值。

例如,当它是默认的Ubuntu桌面环境时,搜索关键词应该变为:’gsettings’和’cron’,那么我们的搜索将引导我们看到有线主题: 背景不会改变使用来自cron的gsettings ,我们可以找到其他解释如下:

如果从您自己的环境(例如,从终端窗口或从启动应用程序)运行脚本,则将设置许多环境变量。 然而, cron使用一组有限的环境变量来运行脚本。

要从cron成功编辑gsettings ,您需要设置DBUS_SESSION_BUS_ADDRESS环境变量。 您可以通过在脚本中添加两行来完成此操作 ,如此处所述…


运行:Daily-Reddit-Wallpaper通过Cron通过启动脚本

在这里,我们将创建一个启动脚本,该脚本将根据所选(通过参数)桌面环境设置必要的环境变量。

1.首先克隆Daily-Reddit-Wallpaper并安装依赖项:

 cd ~ git clone https://github.com/ssimunic/Daily-Reddit-Wallpaper.git cd ~/Daily-Reddit-Wallpaper sudo apt-get install python-pip pip install -r requirements.txt 

2.创建脚本文件 – change_wallpaper_reddit.sh

 cd ~/Daily-Reddit-Wallpaper touch change_wallpaper_reddit.sh chmod +x change_wallpaper_reddit.sh nano change_wallpaper_reddit.sh 

脚本的内容是:

 #!/bin/sh # Reference: https://askubuntu.com/a/911958/566421 # Set the script home directory: SHOME=Daily-Reddit-Wallpaper # Set the output folder in the home directory to save the Wallpapers to: DIR=Pictures/Wallpapers # Set the --time parameter value TIME=now # Check if the Desktop Environment is changed: LAST=$(cat "$HOME/$SHOME/last-desktop-environment.log") if [ "$1" != "$LAST" ] then # Get the name of the last saved wallpaper image: IMG=$(ls -Art $HOME/$DIR | tail -n 1) rm $HOME/$DIR/$IMG fi # Desktop Environment cases: if [ -z ${1+x} ] || [ "$1" = "gnome" ] || [ "$1" = "unity" ] then # Set the necessary environment variables - PID=$(pgrep gnome-session -u $USER) - UBUNTU/UNITY/GNOME: export GNOME_DESKTOP_SESSION_ID=true export DBUS_SESSION_BUS_ADDRESS=$(grep -z DBUS_SESSION_BUS_ADDRESS /proc/$(pgrep gnome-session -n)/environ | cut -d= -f2-) # Run the script: $HOME/$SHOME/change_wallpaper_reddit.py --time $TIME --output $DIR elif [ "$1" = "kde" ] then # Set the necessary environment variables - KUBUNTU/PLASMA/KDE: export KDE_FULL_SESSION=true export DBUS_SESSION_BUS_ADDRESS=$(grep -z DBUS_SESSION_BUS_ADDRESS /proc/$(pgrep startkde -n)/environ | cut -d= -f2-) # Run the script: $HOME/$SHOME/change_wallpaper_reddit.py --time $TIME --output $DIR elif [ "$1" = "mate" ] then # Set the necessary environment variables - Ubuntu MATE/MATE: export DESKTOP_SESSION=mate export DBUS_SESSION_BUS_ADDRESS=$(grep -z DBUS_SESSION_BUS_ADDRESS /proc/$(pgrep mate-session -n)/environ | cut -d= -f2-) # Run the script: $HOME/$SHOME/change_wallpaper_reddit.py --time $TIME --output $DIR elif [ "$1" = "lxde" ] then # Set the necessary environment variables - type 'echo $DISPLAY` to find your current display - LUBUNTU/LXDE: export DESKTOP_SESSION=Lubuntu export DBUS_SESSION_BUS_ADDRESS=$(grep -z DBUS_SESSION_BUS_ADDRESS /proc/$(pgrep lxsession -n)/environ | cut -d= -f2-) export DISPLAY=$(w $(id -un) | awk 'NF > 7 && $2 ~ /tty[0-9]+/ {print $3; exit}') # Run the script: $HOME/$SHOME/change_wallpaper_reddit.py --time $TIME --output $DIR elif [ "$1" = "xfce4" ] then # Set the necessary environment variables - XUBUNTU/XFCE4: export DBUS_SESSION_BUS_ADDRESS=$(grep -z DBUS_SESSION_BUS_ADDRESS /proc/$(pgrep xfce4-session -n)/environ|cut -d= -f2-) # Run the script: $HOME/$SHOME/change_wallpaper_reddit.py --time $TIME --output $DIR # Get the name of the last saved wallpaper image: IMG=$(ls -Art $HOME/$DIR | tail -n 1) # Since 'change_wallpaper_reddit.py' doesn't work properly with xfce4 we shall set the background manually: xfconf-query --channel xfce4-desktop --property /backdrop/screen0/monitor0/workspace0/last-image --set $HOME/$DIR/$IMG # Property list: xfconf-query --channel xfce4-desktop --list # Current settings: xfconf-query -c xfce4-desktop -p /backdrop -lv # Set 'zoomed' style: xfconf-query --channel xfce4-desktop --property /backdrop/screen0/monitor0/workspace0/image-style --set 5 # References: https://askubuntu.com/q/380550/566421 and https://askubuntu.com/q/414422/566421 else echo "Wrong argument. It must be:" echo " - empty (default) = gnome = unity" echo " - kde" echo " - lxde" echo " - mate" echo " - xfce4" fi # Save current value of the Desktop Environment variable: echo "$1" > "$HOME/$SHOME/last-desktop-environment.log" 

此脚本有一个参数 $1 ,它根据所选(从您)桌面环境(DE)确定其行为。 可能的值是:

  • gnomeunityempty (默认) – 当你使用默认的Ubuntu DE时;
  • kde – 当你使用KUbuntu DE时;
  • lxde – 当你使用LUbuntu DE时;
  • mate – 当你使用Ubuntu MATE DE时;
  • xfce4 – 当你使用XUbuntu DE时。

您还可以自定义这些初始参数:

  • SHOME=设置Daily-Reddit-Wallpaper位于系统中的文件夹。
  • DIR=设置主目录中的输出文件夹以将壁纸保存到 – 在上面的脚本中使用默认值( Pictures/Wallpapers )。
  • TIME=设置--time参数的change_wallpaper_reddit.py

3.创建执行change_wallpaper_reddit.sh CronJobcrontab -e )(例如每小时):

  • 如果你使用默认的Ubuntu DE,这个CronJob可能是:

     0 * * * * /home//Daily-Reddit-Wallpaper/change_wallpaper_reddit.sh > /home//Daily-Reddit-Wallpaper/cron.log 2>&1 

    此语法也会带来相同的结果:

     0 * * * * /home//Daily-Reddit-Wallpaper/change_wallpaper_reddit.sh gnome > /home//Daily-Reddit-Wallpaper/cron.log 2>&1 
  • 例如,如果你使用KUbuntu DE,这个CronJob可能是:

     0 * * * * /home//Daily-Reddit-Wallpaper/change_wallpaper_reddit.sh kde > /home//Daily-Reddit-Wallpaper/cron.log 2>&1 
  • 要进行故障排除,请检查日志文件: cat /home/$USER/Daily-Reddit-Wallpaper/cron.log

瞧。 它正在工作!


参考和进一步的reding:

  • 如何在取消设置DISPLAY时以编程方式查找DISPLAY的当前值? (用于crontab)
  • 应该执行到终端窗口的Crontab和C程序
  • 使用xrandr和cron作业调整亮度
  • 如何在SSH或Cron中通过CLI确定当前用户的DE?

请注意cronjab在具有有限环境设置的shell中执行。 我的意思是,当你打开一个终端并输入env时,你会看到很多环境变量; 其中一个最重要的是PATH。 cron作业不会登录,因此不会执行.profile文件。 因此,在您的脚本中,您必须确保设置或补充环境变量,如PATH。
另外,一个cron条目不应该使用〜而是放入完整路径。

在我的系统中,我创建了一个小脚本来列出在cron中启动脚本时设置的环境变量。 正如您在终端中看到的要少得多:

 HOME=/home/willem LANG=en_US.UTF-8 LC_ADDRESS=nl_NL.UTF-8 LC_IDENTIFICATION=nl_NL.UTF-8 LC_MEASUREMENT=nl_NL.UTF-8 LC_MONETARY=nl_NL.UTF-8 LC_NAME=nl_NL.UTF-8 LC_NUMERIC=nl_NL.UTF-8 LC_PAPER=nl_NL.UTF-8 LC_TELEPHONE=nl_NL.UTF-8 LC_TIME=nl_NL.UTF-8 LOGNAME=willem PATH=/usr/bin:/bin PWD=/home/willem SHELL=/bin/sh SHLVL=1 _=/usr/bin/env 

正确的脚本以shebang表达式开头,一些文本解释脚本将执行的操作(几个月后您可能会忘记)然后设置环境变量。 一个小例子(NB Willem是我的用户名:

 #!/bin/bash # Script is created and tested for Bash. # Example script Hello, runs outside a terminal so PATH is minimal. # We must set env vars. # Note I do not use "export PATH=$PATH:..." etc, because I want my progs # directory to be found first. export MYHOME=/home/willem export MYLOGS=$MYHOME/logs export MYPROGS=$MYHOME/prog export PATH=$MYPROGS:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin # # The main code of the script: # echo "Hello: started" > $MYLOGS/Hello.log goodDay >> $MYLOGS/Hello.log # goodDay is also in $MYPROGS ... ... #EOF 

要将脚本放在cron中,请输入crontab -e
你在vi中,所以转到文件末尾并添加:
* * * * * / home / willem / prog /你好

关闭并保存,并查看您的crontab条目/条目: crontab -l