0

Background

The PNG image files I want to use is stored in directories according to date, for example:
/NAS-mein/data/201812/
PNG stored within it like /NAS-mein/data/201812/foo/bar/20181231_1500.png

So I created a symbolic link PNG_path in my home directory
ln -s /NAS-mein/data/201812/ PNG_path

and I'm able to update it manually through:
ln -sf /NAS-mein/data/201812/ PNG_path
which works fine and returns `PNG_path' -> `/NAS-mein/data/201812'

I'm in a CentOS 6.7 environment and I don't have superuser privilege.
The destination directory is created by the others but granted 777 permission, i.e.:
drwxrwxrwx /NAS-mein/
drwxrwxrwx /NAS-mein/data/
drwxrwxrwx /NAS-mein/data/201812/

With Crontab

Then I tried to automatically update this symbolic link on the first day of month, so it will always redirect me to the directory of current date.
I tried start a job in crontab like:
0 0 1 * * ln -sf /NAS-mein/data/$(date "+%Y%m") /home/me/PNG_path >>/home/me/.pngln.log 2>>&1
but this does not work, even without giving any information to the log.
So I tried:
0 0 1 * * cd /home/me/ && ln -sf /NAS-mein/data/$(date "+%Y%m") PNG_path >>.pngln.log 2>>&1
and wrap it into a Bash script like:

#!/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  

but all of above seem not working as the symbolic link does not change, and no any information was logged (i.e. .pngln.log is not created anyway.)

I'm not sure where I did it wrong, or using ln in crontab is just not a legit use?

Edit: I notice that I didn't write the most suspicious part: using date function in ln expression.

1

The percent sign is special in crontab and needs to be escaped if you put your date command there (see man 5 crontab).

Your symbolic link points to a directory. When you run ln again, it will put the link inside that directory.

Example:

$ 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

The solution is to use ln with -n (or --no-dereference) on Linux or on any system with GNU coreutils' ln, and with -h on BSD. This would cause ln to not descend into the directory that the link points to before creating the new link.

A portable solution would be to first explicitly remove the link using rm:

ln -s some_directory link

Later:

rm link && ln -s some_directory link
  • I did some test following your explanation and it worked the way you described, including the problem that I add extra tailing /. But in real case it seem not the same, as no additional symlink was created inside destination directory. I will add some more description about the directory privilege in the question for additional clarity. – ceoper Jan 31 at 9:24
  • @ceoper Did you see what I added about % in crontab at the top of the answer? – Kusalananda Jan 31 at 9:35
  • 1
    Oh god, I mis-read it and thought it was the $ symbol , and was trying around it. I will try to escape % symbol later. – ceoper Jan 31 at 9:56
  • Ok. I tested it on another CentOS 6.8 environment and it worked. I will later try to find out what is preventing me from doing this on that specific machine. – ceoper Jan 31 at 10:11
  • It turns out that in the early trials, the problem was the % in crontab as mentioned by @Kusalananda. And in later trials I wrote 2>>&1 (which I didn't update in my question description...) in my cron and caused the failure and no error message cannot be logged. Now I got things work out and I'll update the question. – ceoper Feb 1 at 2:28
0

I want to sum up the mistakes that cause of the failure of my crontab ln schedule in this answer.
This is much thanks to Kusalananda's answer, I just organize them for record.

First, as mentioned by Kusalananda, if one is trying to update the symlink of a directory, the symlink will be created inside the directory, so one will need to set -n flag for ln, so the algorithm will not follow into the reference.

Good:

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

Not working:

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


Second, as mentioned by Kusalananda, the % has special meaning in cron, so it needs to be escaped.

Good:

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

Not working:

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


Third and the last, though this is actually not really related to cron or ln, that for stderr to append to the same destination of stdout, it cannot be written as 2>>&1. Instead, 2>&1 is correct. (Actually without -v flag for ln, it will output nothing, but one will at least see an empty log is created.)

Good:

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

Not working:

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

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.