Lawliet has asked for the wisdom of the Perl Monks concerning the following question:

Update 2: Thanks to ikegami, it seems the problem was my installation PerlMagick (which is the module Image::Magick). Once I successfully reinstall it I will update once again.

Update: Added a sentence somewhere below for some possible clarification.

I haz (too much lolcatime) have a Perl program that creates a thumbnail from my pictures folder (~/Pictures/wallpapers). The program is located in /var/www/guest where there is a symlink to ~/Pictures/wallpapers and another a directory entitled thumbwalls. As most can guess, thumbwalls is where I try to write the thumbwalls. (I italicized 'try' to indicate failure, as most can guess.)

Let me further lucubrate:

I am using my desktop as my webserver. The following is located in my /etc/apache2/sites-available/default file.

<Directory /var/www/> AddHandler cgi-script .cgi .pl Options ExecCGI Indexes FollowSymLinks MultiViews AllowOverride All Order allow,deny allow from all </Directory>

As most can see, Symlinks are enabled ;).

Continuing on, the folder ~/Pictures/wallpapers has permissions set to "owner: create/delete files, group and others: access files" (not verbatim, as most can guess).

I am not sure what other information I can provide except the problematic code, so here goes.

Oh, wait, I should probably further expatiate the problem. Whenever I run the script it errors out saying it cannot find the specified file (which is /var/www/guest/wallpapers/:D.jpg -- a symlink to ~/Pictures/wallpapers/:D.jpg). I believe the problem may be Apache not wanting to go through the symlink. Note that I use absolute paths because Image::Magick demands I do so (I think). Also note that if I try to use the actual path to the file (not the symlink), it errors in the same way. Note that if I comment out the subroutines (err, comment out the one where I check for errors) it prints out all the pictures as their alt text, as well.

Without further adieu, for all intensive porpoises, code.

# Warnings, strictures, and modules be here. my $path = '/var/www/guest'; my $wallpath = $path.'/wallpapers'; my @walls = <$wallpath/*>; # Start html, table, and so on in place of this comment. # Need a better way to create a new Tr every 6th image for (my $i = 0; $i < $#walls; $i++) { my $currentpic = $walls[$i]; # Less confusion (my $filename = $currentpic) =~ s/.+\/(.+)/$1/; # Remove path my $thumbnail = "thumbwalls/t_$filename"; thumbnailize($currentpic, $thumbnail) unless -e $thumbnail; my $imgres = getInfo($currentpic); if ($i % 6 == 0) { print $query->start_Tr(); } # Print thumb and info about it if ($i % 6 != 0) { print $query->td( $query->a( {href => $currentpic}, img{src=>$ +thumbnail, alt=>$filename}), $query->br(), $imgres, ); next; } if ($i % 6 == 0) { print $query->end_Tr(); } } # End some things, do a little cleanup, the whole works here. sub thumbnailize { my ($pic, $thumb) = @_; my $image = Image::Magick->new; $image->Read($pic) or die $!; # I used die thinking it $image->Scale(geometry => '200x200'); # would catch error. $image->Write(filename => $thumb) or die $!; # It didn't. } sub getInfo { my $pic = shift; my $image = Image::Magick->new; print "workz" if -e $pic; # Prints successfully my $err = $image->Read($pic) or die $!; print $err if $err; # Errs successfully my ($xres, $yres) = $image->Get('x-resolution', 'y-resolution'); return "$xres x $yres"; }

I tried to keep the code relevant as well as show enough information. Feel free to ask for more information (the request may or may not be answered). Also, I have been frequently changing the code for a few days now so there may be some pleonasms. (The italicized 'have' was not used to indicate failure this time. Neither was that 'not'.)

Oh, let me recapitulate in case you have forgotten the problem. Either Apache (or Perl) does not see (or follow) the symlink to the picture.

And you didn't even know bears could type.

Replies are listed 'Best First'.
Re: Apache2 and symlinks
by ikegami (Patriarch) on Jan 07, 2009 at 01:51 UTC

    Based on CB chat, my current understanding follows:

    • You have a Perl script (running as CGI).
    • Said script cannot use Image::Magick to access a file ("~/Pictures/wallpapers/:D.jpg") via a symlink ("/var/www/guest/wallpapers/:D.jpg").
    • The entire Apache business is a red herring because it finds and executes your script.

    Two important points about CGI scripts:

    • The current dir is often set to "/".
    • The user running the script may not be "you".

    Checklist to answer:

    • Check if the symlink is named what you expect it to be named.
    • Check if the image is named what you expect it to be named.
    • Check if the symlink points to the correct file.
    • Check if the variable holds the file name you are expecting it to hold. Note that the tilde doesn't mean home dir in a file name unless it's subject to shell expansion.
    • Check if the user as which your script runs has sufficient permissions to access the directory containing the symlink. That means it needs to be able to access all the directories in the path that leads to the symlink.
    • Check if the user as which your script runs has sufficient permissions to read the directory containing the links.
    • Check if the user as which your script runs has sufficient permissions to access the directory containing the image. That means it needs to be able to access all the directories in the path that leads to the image.
    • Check if the user as which your script runs has sufficient permissions to read the image?
    • Check the error you are getting by opening the symlink using open instead of Image::Magick.
    • Check the error you are getting by opening the image using open instead of Image::Magick.

    Update: Added a couple more.

      Well, to cross out the first bullet, I can say that I use the full path and not the tilde when using the symlink approach. I used the tilde shorthand to explain where the symlink was pointing to.

      To cross out the next 4 bullets I can say that open(PIC, '<', $pic) or die "hurr"; led to no deaths leading to me believe I am bad at installing modules :(.

      Time to try reinstalling Image::Magick~

      (The tilde was not shorthand this time. :P)

      Update: Whoops, you updated your node adding even more bullets! (and removed one)! Is my open() success a false positive?

      Updated update to be factually correct.

      And you didn't even know bears could type.

Re: (Updated -- Apache2 is irrelevant) Apache2 and symlinks
by shagbark (Acolyte) on Jul 12, 2012 at 04:48 UTC

    This may be a failure of symlink due to .jpg being a binary file. A .png file, linked to through Windows 7 symbolic links, cannot be opened by Windows Photo Viewer, Gimp, or Firefox through the symbolic link, whether you make that link using Perl and Win32::Symlink, or from the Cygwin command line, and whether you use absolute or relative paths. This may be some bizarre Windows protection problem, although links to text files made in the same way have no problem, and the "diff" command indicates no difference between the .png and the symlink to it.

    This, for example, links link.png to graph.png, but you can't open the PNG through link.png:

    require Win32::Symlink; Win32::Symlink->import(); use warnings; use strict; use Cwd; my $cwd = getcwd; my $a = 'stories/graph.png'; my $link = 'link.png'; unlink("$cwd/$link") if -e $link; symlink("$cwd/$a", "$cwd/$link"); exit; $diff link.png stories.graph.png [no difference]
    This also does not work:
    ln -s stories/graph.png link.png
    Nor this:
    export pwd=`pwd` ln -s $pwd/stories/graph.png $pwd/link.png
    It appears to be a bug in how Windows 7 implements symlinks, having nothing to do with Perl. BUT, hard links DO work:
    ln stories/graph.png link.png
    produces a link that you can use. The 'symlink' command is supposed to be equivalent to "ln -s", which does not work.