I am trying to write a runLinuxCommand
that would run either on Windows (with Windows Subsystem for Linux) or on Linux (and perhaps OSX as it is Unix like).
I had some issues with exec("dir", $result, $code)
returning $code ==> 1
. I then changed the user running PHP in IIS to be my current logged in user (which is an administrator). I know, this is not ideal, but for now, I want to reach my goal. I'll try to reduce rights afterward. And... it worked!
So, I tried to execute exec("wsl date", $result, $code)
, but no luck, still an exit code of 1. Yes, opening a command prompt and executing wsl date
does work. Either with the logged in user or as administrator.
The only thing I can see for now is it takes too much time to initialize WSL, but quite not sure at all.
The one in the issue section
exec('C:\\Windows\\System32\\wsl.exe date', $result, $code);
Same result.
exec('start /B /WAIT C:\Windows\System32\wsl.exe date', $result, $code);
Hanging... never getting through this line.
exec('start /B /WAIT cmd /C C:\\Windows\\System32\\wsl.exe date', $result, $code);
No error. No result / output.
$WshShell = new \com("WScript.Shell");
$oExec = $WshShell->Exec("C:\\Windows\\System32\\wsl.exe date");
$out = $oExec->StdOut->ReadLine();
Now I have a specific error message when running the second line: File not found
. I can assure you that C:\Windows\System32\wsl.exe
exists.
I already confirmed using $oExec = $WshShell->Run("whoami", 0 , true);
as second line that the user is the one I am logged in (an administrator account from which I can test using a terminal).
I searched a lot about it, and I found nothing (well, everything I found was not specific).
So, after some tribulations, I figured out the issue was coming from the PHP 32 bits version. Using the 64 bits version calling exec('wsl date', $result, $code);
works perfectly.
So, for those interested in the class I built:
class Host {
private function __construct() {}
/**
* Get if the host is Windows
* @return boolean
*/
public static function isWindows() {
$uname = strtolower(php_uname('s'));
return strpos($uname, "win") === 0;
}
/**
* Get if PHP is 64 bits or not (32 bits)
* @ref https://code-boxx.com/check-php-version/#:~:text=To%20check%20if%20you%20are,and%208%20for%2064%2Dbit.
* @return boolean
*/
public static function isPhp64bits() {
if (isset($_SERVER["PROCESSOR_ARCHITECTURE"])) {
// Windows IIS validation
return $_SERVER["PROCESSOR_ARCHITECTURE"] != "x86";
}
return PHP_INT_SIZE == 8;
}
public static function runLinuxCommand($command) {
if (self::isWindows()) {
if (self::isPhp64bits()) {
$wslExecutor = "wsl";
} else {
$wslExecutor = "C:\\Windows\\Sysnative\\wsl.exe";
}
$command = "$wslExecutor $command";
} else {
putenv('LANG=en_US.UTF-8'); // Ensure the output is UTF-8
}
$result = [];
$exitCode = -1;
exec($command, $result, $exitCode);
return new ExecReturn($result, $exitCode);
}
}
This is no more needed : For the WSLExecutor software, quite simple, but anyhow: https://github.com/djon2003/WSLExecutor
I know, the framework calls aren't included, but I won't post the whole framework. Moreover, they are methods that can be easily implemented.
Edit #1
With the help of NotTheDr01ds, I no more need the C# software WSLExecutor.