php shell_exec not working on windows - php

I am on Windows. I have a string as follows
Ra6tRR8DIsoll/7O5o6DBfRvlbhdj4mGmivRXYiDHD1JpY1WIMpI5HycXp/IsnUF
What I am trying to do is perform a shell_exec from php to my console app . The console app command line is as follows
consoleapp decrypt Ra6tRR8DIsoll/7O5o6DBfRvlbhdj4mGmivRXYiDHD1JpY1WIMpI5HycXp/IsnUF
However when I try to run shell_exec using the command above I get a null as a result. the command works on the console, though.
Is it because there are special characters in the string ? I was looking at escapeshellarg and wondering if it could help resolve this issue ?
following is my code . I am calling the doDecreyptWithTime method.
private function doDecryptWithTime($string)
{
$command = "aesencryptdecrypt.exe decrypt ". escapeshellarg(trim($string));
// dd($command);
return exec($command);
}
private function doDecrypt($string)
{
$command = $this->generateEntireCommand(EncryptionCommands::Decrypt). ' ' .$string;
return shell_exec($command);
// return explode(Config::get('myconfig.DecryptDelimiter'),$output);
}
private function generateEntireCommand($command)
{
if($command == EncryptionCommands::Encrypt)
return $this->generatePath(). ' '. EncryptionCommands::Encrypt;
elseif($command == EncryptionCommands::Decrypt)
return $this->generatePath(). ' '.EncryptionCommands::Decrypt;
elseif($command == EncryptionCommands::DecryptWithTime)
return $this->generatePath(). ' '.EncryptionCommands::DecryptWithTime;
}
private function generatePath()
{
$fullEncryptFileName = null;
$encryptFileName = Config::get('myconfig.EcryptionFileName');
if(!is_null(Config::get('myconfig.EcryptionFileName')))
{
$fullEncryptFileName = public_path().DIRECTORY_SEPARATOR.Config::get('myconfig.EncryptFileLocation').DIRECTORY_SEPARATOR.$encryptFileName;
}
else
{
$fullEncryptFileName = public_path().DIRECTORY_SEPARATOR.$this->fileLocation.DIRECTORY_SEPARATOR.$encryptFileName;
}
if(!is_null($fullEncryptFileName))
return $fullEncryptFileName;
else
throw new Exception('could not generate the filename');
}
Update 1 :
I am on php 5.5 so i Believe that the safe_mode functionality is not available any more. Also I have checked the disabled functions list, shell_exec, exec are not listed there .
please suggest!

Related

Trying to amemd CronJob's Via a PHP file

I have a hosting platform that at midnight resets all cronjob added on there system to 15 from what ever they where set to. Our plan is to set up a script that run's every 8hrs and resets these back, so the process they manage are minimally interrupted. It is shared hosting, but hosting companies solution it an upgrade and a massive rise in costs.
The server specs are cPanel Version - 70.0 (build 69) | Apache Version - 2.4.39 |PHP Version - 7.2.18 |MySQL Version - 10.2.24-MariaDB-cll-lve |Architecture - x86_64 | Operating System - linux
We have been suggested using a PHP class called Crontab to achieve this.
When we add a job, it appears in our cron job section of our server, but if we try to delete it from the server we get the following error 'Error New Lines are not permitted in crontab entries'. How ever we can remove the job via the Crontab class.
<?php
class Crontab {
static private function stringToArray($jobs = '') {
$array = explode("\r\n", trim($jobs)); // trim() gets rid of the last \r\n
foreach ($array as $key => $item) {
if ($item == '') {
unset($array[$key]);
}
}
return $array;
}
static private function arrayToString($jobs = array()) {
$string = implode("\r\n", $jobs);
return $string;
}
static public function getJobs() {
$output = shell_exec('crontab -l');
return self::stringToArray($output);
}
static public function saveJobs($jobs = array()) {
$output = shell_exec('echo "'.self::arrayToString($jobs).'" | crontab -');
return $output;
}
static public function doesJobExist($job = '') {
$jobs = self::getJobs();
if (in_array($job, $jobs)) {return true;} else {return false;}
}
static public function addJob($job = '') {
if (self::doesJobExist($job)) {
return false;
} else {
$jobs = self::getJobs();
$jobs[] = $job;
return self::saveJobs($jobs);
}
}
static public function removeJob($job = '') {
if (self::doesJobExist($job)) {
$jobs = self::getJobs();
unset($jobs[array_search($job, $jobs)]);
return self::saveJobs($jobs);
} else {
return false;
}
}
}
//$output = shell_exec('crontab -l'); //Check server output
//echo nl2br($output); //Make it readable
Crontab::addJob('*/15 * * * * /opt/alt/php56/usr/bin/php -q /home/path/bob.php process-log >/dev/null 2>&1');
Crontab::removeJob('*/15 * * * * /opt/alt/php56/usr/bin/php -q /home/path/bob.php process-log >/dev/null 2>&1');
?>
The reason this is a concern is that for there to be a server error, then code inputting the cronjob must not be doing it right, I have hear of issue when running similar processes on windows servers, but the php file running the code is in the root of the linux server, so wasn't expecting to have issues.
IF someone could explain why this error is occurring and how to fix it, that would be greatly appreciated, let me know if you need any more info.
Cheers in advance.

Behat: Cannot kill web server process when done testing

I'm testing a web crawler script. I'm using the php builtin webserver to test against pages locally.
I can start the server but I cannot kill the process because it is already killed (I get the exception that I set Could not kill the testing web server).
Here is my attempt:
<?php
use Behat\Behat\Tester\Exception\PendingException;
use Behat\Behat\Context\Context;
use Behat\Behat\Context\SnippetAcceptingContext;
use Behat\Gherkin\Node\PyStringNode;
use Behat\Gherkin\Node\TableNode;
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
use Behat\Behat\Hook\Scope\AfterScenarioScope;
/**
* Defines application features from the specific context.
*/
class FeatureContext implements Context, SnippetAcceptingContext
{
const TESTING_BASE_URL = 'http://127.0.0.1:6666';
const TESTING_DIR = '/tmp/testDirectory';
private $pid;
/**
* Initializes context.
*
* Every scenario gets its own context instance.
* You can also pass arbitrary arguments to the
* context constructor through behat.yml.
*/
public function __construct()
{
}
/**
* #BeforeScenario
*/
public function before(BeforeScenarioScope $scope)
{
// Create testing directory holding our pages
if (!is_dir(self::TESTING_DIR)) {
if (!mkdir(self::TESTING_DIR)) {
throw new \Exception('Cannot create the directory for testing');
}
}
// Start the testing server
$command = sprintf(
'php -S %s -t $%s >/dev/null 2>&1 & echo $!',
escapeshellarg(self::TESTING_BASE_URL),
escapeshellarg(self::TESTING_DIR)
);
$output = [];
exec($command, $output, $return_var);
if ($return_var !== 0) {
throw new \Exception('Cannot start the testing web server');
}
$this->pid = (int)$output[0];
echo sprintf(
'Testing web server started on %s with PID %s %s %s',
self::TESTING_BASE_URL,
(string)$this->pid,
PHP_EOL,
PHP_EOL
);
}
/**
* #AfterScenario
*/
public function after(AfterScenarioScope $scope)
{
// ... kill the web server
$output = [];
exec('kill ' . (string) $this->pid, $return_var);
if ($return_var !== 0) {
throw new \Exception('Could not kill the testing web server (PID ' . (string) $this->pid . ')');
}
echo 'Testing web server killed (PID ', (string) $this->pid, ')', PHP_EOL, PHP_EOL;
// ... remove the test directory
$o = [];
exec('rm -rf ' . escapeshellarg(self::TESTING_DIR), $o, $returnVar);
if ($returnVar !== 0) {
throw new \Exception('Cannot remove the testing directory');
}
}
// ...
}
I also tried various things like putting it all in the constructor, using register_shutdown_function, without any success.
What am I missing? Any idea on how I can solve this?
Instead of just "not caring about killing the server process" (because to me it looks like it's gone when I try to kill the process, hence the error, I can't find it when I issue ps aux | grep php on the command line after running behat), isn't it "cleaner" to kill it as I attend to?
The exec call is missing the output parameter:
exec('kill ' . (string) $this->pid, $output, $return_var);
Unless this is set, the exception will always be thrown, because $return_var is actually the output of the command (which is an array not an integer).

PHP shell_exec does not work for two different app version

I am experiencing an interesting strange issue with shell_exec...
Description
I develop PHP web app that uses C++ backend app for calculations. Server is running on linux and I use shell_exec for C++ program execution. I updated version of my C++ app and since then shell_exec doesn't work, but
I've checked both versions of C++ app have 777 rights
Both versions run flawlessly from a console
Both versions were tested for same data
Both versions were tested on two different PCs/webservers with same results
For both versions the webapp PHP frontend is exactly the same
Second version (that can't be launched) runs faster then previous one
Questions
Have you ever experienced a similar problem?
Is it possible that in shell_exec a problem could occur, that during standard execution from console doesn't?
Piece of PHP code
class LauncherManager extends Nette\Object {
private $wwwDir;
private $db;
private $f;
public function __construct($wwwDir, \DibiConnection $db) {
$this->wwwDir = $wwwDir;
$this->db = $db;
$this->f = (new Dao\DaoFactory())->setDb($db);
}
public function execMeasurement($measurementId) {
$this->execGenetrac(" -m $measurementId");
}
public function execSamples($analysisId) {
$this->execGenetrac(" -s $analysisId");
}
public function execAnalysis($analysisId) {
$this->execGenetrac(" -a $analysisId");
}
public function execGenetrac($params) {
// Check path to genetrac can be set
$path = $this->wwwDir . "/genetrac";
$this->checkPathExist($path);
// Check library path
$lib = './lib';
$expl = 'export LD_LIBRARY_PATH="' . $lib . '"';
$this->checkPathExist($path . "/" . $lib);
// Check genetrac executable exist
$this->checkPathExist($path . "/genetrac");
// Launch genetrac with parameters
$this->exec("cd $path; $expl; ./genetrac $params");
}
public function exec($command) {
return shell_exec($command);
}
...
shell_exec returns NULL in two situations:
an error occurs
executed program returns no output
In order to distinguish these situations use exec() instead:
public function exec($command) {
exec($command, $arrOutputLines, $intReturnStatus);
return join("", $arrOutputLines);
}
You can debug this code by var_dump'ing $arrOutputLines and $intReturnStatus (these are the array of lines that your program printed out and the numeric exit status of your program (0 usually means OK, non-zero means error)).

How to enable pathautocompletion from windows commandline

I want to ask the user to locate a folder on the (windows) commandline.
Usually you'll be able to use autocomplete with the [tab] key.
But not if I ask this from a phpscript.
I use this class:
<?php
class CLQuestion
{
protected $_awnser;
protected $_options;
protected $_question;
public function __construct($question, $options = array())
{
$this->_question = $question;
$this->_options = $options;
$this->askQuestion();
$this->waitForAwnser();
}
protected function askQuestion()
{
echo PHP_EOL . $this->_question . PHP_EOL;
}
protected function waitForAwnser()
{
while (true) {
$response = strtolower(trim(fgets(STDIN)));
// are options given?
if (empty($this->_options)) {
// no options given, so the response is our awnser
$this->_awnser = $response;
break;
} else if (!empty($this->_options) && in_array($response, $this->_options)) {
// options given and found in options
$this->_awnser = $response;
break;
} else {
// options given and not found.
echo PHP_EOL . 'Please use one of these options: ';
echo PHP_EOL . " " . implode(PHP_EOL . " ", $this->_options);
echo PHP_EOL;
continue;
}
}
}
public function getAwnser()
{
return $this->_awnser;
}
}
With this usage:
<?php
$question = new CLQuestion('Where is you folder located?');
$question->getAwnser(); // path typed
Windows CMD will give me a way to interact, but when i use the [tab] key, it does not autocomplete but it show a tab.
Am I able to activate path autocompletion in some way?
autocompletion is a feature of a windows shell prompt.
When you run an application like:
php script.php
this application gains control over STDIN and STDOUT and magic shell features like autocompletion will work no more until this app finishes.
This for example allows you to run one shell inside another.
If you need autocompletion in your script, you will need to implement it yourself. Instead of reading whole line with fgets(STDIN) you could read it char by char with fgetc(STDIN) and when the char will equal "\t" you would have to list files in current directory with php functions and check witch paths are matching to what user have written till now. So you will basically have to re-implement fgets adding magic autocompletion feature.
But instead of doing this and implementing your own shell I guess it would be far more better to make the folder location a script argument:
<?php
if(empty($argv[1])) die("usage: php script.php folderpath");
echo "your folder is located at:" . $argv[1];
So you could call it from windows shell like:
#php script.php
usage: php script.php folderpath
#php script.php foldername
your folder is located at: foldername
And then the autocompletion feature will work.

Using shell with Zend Framework

I'm curios if Zend has a component which can make use of the shell. For example I want to do an shell command like this:
mysqldump --compact --uroot --ppass mydatabase mydable >test.sql
from a controller.
If there isn't, do you know a way how to dump data from tables in Zend Framework?
update:
I've found a way here http://www.zfsnippets.com/snippets/view/id/68
There's no direct exec() support in the zend framework. the closest to command line support there is the Zend_Console class, but it's meant for getting arguments from the command line.
I would wrap the exec() function as a process object and work with that. Here's a nice example from the php docs:
<?php
// You may use status(), start(), and stop(). notice that start() method gets called automatically one time.
$process = new Process('ls -al');
// or if you got the pid, however here only the status() metod will work.
$process = new Process();
$process.setPid(my_pid);
?>
<?php
// Then you can start/stop/ check status of the job.
$process.stop();
$process.start();
if ($process.status()){
echo "The process is currently running";
}else{
echo "The process is not running.";
}
?>
<?php
/* An easy way to keep in track of external processes.
* Ever wanted to execute a process in php, but you still wanted to have somewhat controll of the process ? Well.. This is a way of doing it.
* #compability: Linux only. (Windows does not work).
* #author: Peec
*/
class Process{
private $pid;
private $command;
public function __construct($cl=false){
if ($cl != false){
$this->command = $cl;
$this->runCom();
}
}
private function runCom(){
$command = 'nohup '.$this->command.' > /dev/null 2>&1 & echo $!';
exec($command ,$op);
$this->pid = (int)$op[0];
}
public function setPid($pid){
$this->pid = $pid;
}
public function getPid(){
return $this->pid;
}
public function status(){
$command = 'ps -p '.$this->pid;
exec($command,$op);
if (!isset($op[1]))return false;
else return true;
}
public function start(){
if ($this->command != '')$this->runCom();
else return true;
}
public function stop(){
$command = 'kill '.$this->pid;
exec($command);
if ($this->status() == false)return true;
else return false;
}
}
?>
It's also let you stop and check the status of a job.

Categories