如何通过 crontab 定期更新符号链接 (ln -sf)

如何通过 crontab 定期更新符号链接 (ln -sf)

背景

我想要使​​用的PNG图像文件根据日期存储在目录中,例如:
/NAS-mein/data/201812/
PNG存储在其中,例如/NAS-mein/data/201812/foo/bar/20181231_1500.png

PNG_path所以我在我的主目录中创建了一个符号链接
ln -s /NAS-mein/data/201812/ PNG_path

我可以通过以下方式手动更新它:
ln -sf /NAS-mein/data/201812/ PNG_path
工作正常并返回`PNG_path' -> `/NAS-mein/data/201812'

我在CentOS 6.7环境中,没有超级用户权限。
目标目录是其他人创建的,但授予了777权限,即:
drwxrwxrwx /NAS-mein/
drwxrwxrwx /NAS-mein/data/
drwxrwxrwx /NAS-mein/data/201812/

使用定时任务

然后我尝试在每月的第一天自动更新此符号链接,因此它总是将我重定向到当前日期的目录。
我尝试在 crontab 中启动一项工作,例如:
0 0 1 * * ln -sf /NAS-mein/data/$(date "+%Y%m") /home/me/PNG_path >>/home/me/.pngln.log 2>>&1
但这不起作用,即使没有向日志提供任何信息。
所以我尝试:
0 0 1 * * cd /home/me/ && ln -sf /NAS-mein/data/$(date "+%Y%m") PNG_path >>.pngln.log 2>>&1
并将其包装到 Bash 脚本中,例如:

#!/bin/bash  
/bin/unlink  "/home/me/PNG_path"  
/bin/ln -sf /NAS-mein/data/$(date "+%Y%m")  PNG_path >>/home/me/.pngln.log  2>>&1  

但上述所有内容似乎都不起作用,因为符号链接没有更改,并且没有记录任何信息(即.pngln.log无论如何都没有创建。)

我不确定我哪里做错了,或者使用lnincrontab只是不合法的用途?

编辑:我注意到我没有写最可疑的部分:在ln表达式中使用日期函数。

答案1

百分号在 crontab 中很特殊,如果您将date命令放在那里,则需要对其进行转义(请参阅 参考资料man 5 crontab)。

您的符号链接指向一个目录。当您ln再次运行时,它会将链接放入该目录中。

例子:

$ mkdir real
$ ln -sf real link
$ tree
.
|-- link -> real
`-- real

1 directory, 1 file
$ ln -sf real link
$ tree
.
|-- link -> real
`-- real
    `-- real -> real

1 directory, 2 files

解决方案是在 Linux 或任何带有 GNU coreutils' 的系统上使用lnwith -n(或) ,在 BSD 上使用 with。这将导致在创建新链接之前不会下降到链接指向的目录。--no-dereferenceln-hln

一个可移植的解决方案是首先使用以下命令显式删除链接rm

ln -s some_directory link

之后:

rm link && ln -s some_directory link

答案2

crontab ln我想在这个答案中总结一下导致我的日程安排失败的错误。
这非常感谢Kusalananda的回答,我只是整理一下以供记录。

首先,正如 Kusalananda 所提到的,如果尝试更新目录的符号链接,符号链接将在目录内创建,因此需要设置-n标志ln,因此算法将不会遵循引用。

好的:

ln -nsf  /NAS-mein/data/$(date "+%Y%m")  PNG_path

不工作:

ln -nsf  /NAS-mein/data/$(date "+%Y%m")  PNG_path


其次,正如 Kusalananda 提到的, cron%在 cron 中具有特殊含义,因此需要对其进行转义。

好的:

0 0 1 * *  /bin/ln -nsf  /NAS-mein/data/$(date "+\%Y\%m")  PNG_path

不工作:

0 0 1 * *  /bin/ln -nsf  /NAS-mein/data/$(date "+%Y%m")  PNG_path


cron第三也是最后一个,虽然这实际上与or 没有真正的关系ln,但为了stderr附加到 的相同目的地stdout,它不能写成2>>&1。相反, 2>&1是正确的。 (实际上没有-v标志 for ln,它不会输出任何内容,但至少会看到创建了一个空日志。)

好的:

0 0 1 * *  /bin/ln -nsf  /NAS-mein/data/$(date "+\%Y\%m")  PNG_path  >>.log  2>&1

不工作:

0 0 1 * *  /bin/ln -nsf  /NAS-mein/data/$(date "+\%Y\%m")  PNG_path  >>.log  2>>&1

相关内容