0

I'm having problems with the exec php function. When I do:

ls -al /dev/sdf1  

This doesn't found the archive (ls: cannot access /dev/sdf1: No such file or directory), but if I run this command, in console that show me the information. What can I do? That happen even running the php script as a root!!

$mountcommand = "ls -al /dev/$unit  2>&1";
exec("$mountcommand", &$mountoutput, &$mountresult);
print_r($mountoutput);
echo "\n$mountcommand\n\n";

This is in a forked process

ldcl289
  • 41
  • 1
  • 8
  • It works for me. Show us how you're using it. – Jonah Dec 16 '10 at 21:20
  • Is Linux running with SELinux enabled? Or via some other kind of chroot jail? Actually, now that I think about it, you probably are in a [chroot jail](http://en.wikipedia.org/wiki/Chroot)... – ircmaxell Dec 16 '10 at 21:25
  • Starting the script, I do chroot("/"), run as a root, and still nothing!! – ldcl289 Dec 16 '10 at 21:33
  • 1
    Execute `passthru('ls -la /')` and see what it comes up with. Is that the `/` directory? or is it some other directory? – ircmaxell Dec 16 '10 at 21:36
  • You don't need the `&` for `$mountoutput` or `$mountresult`. The function defines those arguments as pass-by-reference itself. – Jonah Dec 16 '10 at 21:42
  • `chroot('/')` won't break you out of a chroot. I think `chroot('/')` is pretty much always a no-op. You should use @ircmaxell's passthru or `readlink /proc/pid-of-php/root` – derobert Dec 16 '10 at 21:42
  • I execute passthru("ls -la /") and it show me all the content of "/", but if I change "/" for "/dev/$unit" it still doesnt work!! – ldcl289 Dec 16 '10 at 21:52
  • @ldcl: Try just `/dev` and see if you see that `$unit` in there manually... – ircmaxell Dec 16 '10 at 22:03
  • It works, but sdf1 isn't in the list. but if I run the same command in the shell it is – ldcl289 Dec 16 '10 at 22:08
  • Maybe still, the PHP process is seeing a chroot's /dev. Compare the output of `ls -id /dev` from PHP with `ls -id /dev' from the commandline. It they(inode #'s) are different then the PHP proc has its own private /dev; if they are the same and the inode isn't 2, it's probably the same /dev; but if the inode is "2" all bets are off. I'm thinking sdf1 is a removable volume that only shows up in the "real" /dev. – frayser Dec 16 '10 at 23:07
  • Both output are the same! And about sdf1, it is a iscsi drive, with a session started in the same php, is the code run before the ls (here is the source of my problem http://stackoverflow.com/questions/4455841/error-on-mount-through-php-exec) – ldcl289 Dec 17 '10 at 14:42
  • The outputs of `ls -id /dev` doesn't mean much unless the inode reported was NOT *inode #2*. If they were both some odd number like 142, chances are /dev is the same directory on the webserver and at the commandline. It they are different numbers, they are different dirs. Okay, if the PHP session is responsible for creating /dev/sdf1, then that part(iscsiadm) might be failing. When PHP runs the command to connect to a target iSCSI dev. Check the return status from the *exec()* call, and capture any messages if you can. Put
     tags around the PHP and see the result in a browser
    .
    – frayser Dec 18 '10 at 12:42

2 Answers2

0

Works for me.

The disks:

frayser@gentoo ~/doc/Answers/src/PHP $ disk

sda     111.790 GB
sdb     233.762 GB
sdc     233.762 GB
sdd     233.762 GB
sde     279.481 GB
------------------
Total:  1092.558 GB

Using hde:

frayser@gentoo ~/doc/Answers/src/PHP $ l /dev/sde
brw-rw---- 1 root disk 8, 64 Dec  2 13:36 /dev/sde

Using PHP:

frayser@gentoo ~/doc/Answers/src/PHP $ php lsdev.php 
Z: brw-rw---- 1 root disk 8, 64 Dec  2 13:36 /dev/sde

The script:

frayser@gentoo ~/doc/Answers/src/PHP $ cat lsdev.php 
<?php
$z=exec("ls -lr /dev/sde");
print "Z: " . $z . "\n";
?>

Update

It also works with ls -al. Please show your script.

Update 2

Along the lines of the chroot suggestion by ircmaxell: Supposing that /dev, as seen in the PHP process, was a special chroot facsimile of the real one. And supposing that /dev/sdf1 is a removable device. The when sdf1(the media) is inserted the system automatically creates the device in the real /dev; but the chroot version isn't updated. So, to detect this situation look for differences between /dev as seen from PHP and from the commandline.

One test is ls -id on /dev(from PHP and the commandline). This prints the inode of /dev. Is there a mismatch in inode numbers?

Is /dev/sdf1 removable? Is it mounted? If it is mounted; does the PHP process see the mounted filesystem: ls $mount_point from PHP it.

There are other chroot tests listed on Stack Overflow and elsewhere; but I haven found many good ones: If a chroot is done correctly, it is hard to detect.

Update 3

This may be what is happening: The device (/dev/sdf1) takes a while to appear after it is created; so it is necessary to pause between creating the device and attempting to mount it:

Before: The device is created; but it isn't there...

Array
(
    [0] => Logging out of session [sid: 4, target: iqn.2004-08.org.frayser:gen2-dummy.ad4s0.dos.e, portal: 172.16.0.1,3260]
    [1] => Logout of [sid: 4, target: iqn.2004-08.org.frayser:gen2-dummy.ad4s0.dos.e, portal: 172.16.0.1,3260]: successful
    [2] => Logging in to [iface: iface0, target: iqn.2004-08.org.frayser:gen2-dummy.ad4s0.dos.e, portal: 172.16.0.1,3260]
    [3] => Login to [iface: iface0, target: iqn.2004-08.org.frayser:gen2-dummy.ad4s0.dos.e, portal: 172.16.0.1,3260]: successful
    [4] => ls: cannot access /dev/sdg: No such file or directory
)

{ test -b /dev/sdg && sudo iscsiadm -m node -T iqn.2004-08.org.frayser:gen2-dummy.ad4s0.dos.e -u; sudo iscsiadm -m node -T iqn.2004-08.org.frayser:gen2-dummy.ad4s0.dos.e -l; ls -al /dev/sdg ;} 2>&1

After: Added a 1-second pause, and the device (sdg) is available...

Array
(
    [0] => Logging out of session [sid: 5, target: iqn.2004-08.org.frayser:gen2-dummy.ad4s0.dos.e, portal: 172.16.0.1,3260]
    [1] => Logout of [sid: 5, target: iqn.2004-08.org.frayser:gen2-dummy.ad4s0.dos.e, portal: 172.16.0.1,3260]: successful
    [2] => Logging in to [iface: iface0, target: iqn.2004-08.org.frayser:gen2-dummy.ad4s0.dos.e, portal: 172.16.0.1,3260]
    [3] => Login to [iface: iface0, target: iqn.2004-08.org.frayser:gen2-dummy.ad4s0.dos.e, portal: 172.16.0.1,3260]: successful
    [4] => brw-rw---- 1 root disk 8, 96 Dec 18 05:27 /dev/sdg
)

{ test -b /dev/sdg && sudo iscsiadm -m node -T iqn.2004-08.org.frayser:gen2-dummy.ad4s0.dos.e -u; sudo iscsiadm -m node -T iqn.2004-08.org.frayser:gen2-dummy.ad4s0.dos.e -l; sleep 1; ls -al /dev/sdg ;} 2>&1

The PHP with the pause ...

<pre>
<?php
$unit='sdg';
$reset="test -b /dev/sdg && sudo iscsiadm -m node -T iqn.2004-08.org.frayser:gen2-dummy.ad4s0.dos.e -u";

$connect="sudo iscsiadm -m node -T iqn.2004-08.org.frayser:gen2-dummy.ad4s0.dos.e -l";

$test="ls -al /dev/$unit";

$mountcommand = "{ $reset; $connect; sleep 1; $test ;} 2>&1";
exec("$mountcommand", $mountoutput, $mountresult);
print_r($mountoutput); 
echo "\n$mountcommand\n\n";
?>
</pre>

The /etc/sudoers is configured the same as reported in the previous question about mount failing from PHP.

So add a second or two of sleep() after iscsiadm creates the device. The sleep can be done in PHP instead of in the exec() of the shell.

Community
  • 1
  • 1
frayser
  • 1,754
  • 10
  • 17
  • 4
    I present you the [`Works on My Machine Certificate`](http://www.codinghorror.com/blog/2007/03/the-works-on-my-machine-certification-program.html)... Congratulations! – ircmaxell Dec 16 '10 at 21:28
  • Thanks, I have made some proves with the sleep and it looks like it works!! I have to do another proves running the command in other servers by ssh, but thanks!! – ldcl289 Jan 03 '11 at 15:41
0

I fix it with a sleep between this code and the code that gave me the "unit"

ldcl289
  • 41
  • 1
  • 8