I want to run php script and pass parameters to it. Parameter are in array.
I json_encode array:
$bot = array(
'timing' => '* * * * *',
'path' => '/sompath/'
);
$bot = json_encode($bot);
And send it to script:
exec('nohup php script.php "' . $bot . '" > /bot.log 2>&1 &');
But then, in script, I don' receive arguments:
print_r($argv[1]); // {path:/sompath/,frequency:*
Looks like special symbols like asterisks are not parsed and break json.
How do I pass array to another script and be shure that all arguments are kept?
If you want to pass the json data as a string you should first escape it:
$bot = array(
'timing' => '* * * * *',
'path' => '/sompath/'
);
$bot = json_encode($bot);
$bot=escapeshellarg($bot);
And then on the receiving script:
print_r(json_decode($argv[1]));
It was simple. Should use urlencode to pass json correctly.
exec('nohup php script.php "' . urlencode($bot) . '" > /bot.log 2>&1 &');
And then, in in script.php:
$params = urldecode($argv[1]);
$params = json_decode($params, true);
I can't send arguments using nohup. By the way, this code is working for me!
$arg1 = escapeshellarg("Hello World");
$ouput = shell_exec("php file.php {$arg1} >/dev/null 2>&1 &");
file.php
$argument = $argv[1];
Related
I am trying to run a lengthy command from a remote server on php using screen, but i want to make sure that the screen is killed at the end of the command. So i am trying to use "echo $STY" to get the screen id and kill it that way. for some reason, this is not working. Any ideas:
ssh2_exec($conn, 'screen');
$getscreen =ssh2_exec($conn, 'echo $STY');
stream_set_blocking($getscreen, true);
$stream_outA = ssh2_fetch_stream($getscreen, SSH2_STREAM_STDIO);
$valA =fgets($stream_outA,160);
$scrnids =explode('.',$valA);
var_dump($scrnids);
$killcommand = 'screen -X -S '.$scrnids[0].' kill';
$stream = ssh2_exec($conn, $command);
.....
ssh2_exec($conn, $killcommand);
ssh2_exec($conn, 'exit'); //just in case
unset($conn);
the var dump just outputs:
array (size=1)
0 => string '
' (length=1)
I'm trying to run integration tests against some of our AMP pages to see if they validate. AMP runs validation if you append #development=1 to a URL and puts the results in console.log. I need to be able to read console.log to check this.
This is what I have so far:
$caps = DesiredCapabilities::firefox();
$caps->setCapability('loggingPrefs', array('browser'=>'ALL'));
//connect to selenium
$webdriver = RemoteWebDriver::create('http://127.0.0.1:4444/wd/hub', $caps);
$webdriver->get('https://www.example.com/amp/page.html#development=1');
sleep(10);
$logs = $webdriver->manage()->getLog('browser');
var_dump($logs);
Using Facebook's webdriver for PHP. I can get the logs back, but it doesn't seem to include anything from console.log. How can I capture this data?
As far as I can tell, the Facebook PHP WebDriver implementation does not seem to implement any of the LoggingPreferences "facilities". However, because PHP is what-I-believe-is-called weakly typed, you can "cheat" by making a call to:
$chromeCapabilities->setCapability( 'loggingPrefs', ['browser' => 'ALL'] );
And then later, call (say)
var_dump( $chromeDriver->manage()->getLog( 'browser' ) );
to access the console log.
The following is a working sample I used to get this working after about 30 hours of investigation - I hope it helps someone! It can use Selenium or not, if not, then it calls the ChromeDriver directly. The test site includes some JavaScript to explicitly write to the console.log:
<?php
require_once (__DIR__.'/../vendor/autoload.php');
use Facebook\WebDriver\Remote\DesiredCapabilities;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\Chrome;
$javaPath = '"C:\\Program Files (x86)\\Common Files\\Oracle\\Java\\javapath\\java.exe"';
$seleniumPath = '"'. __DIR__ . '\\..\\selenium-server-standalone-3.141.5.jar"';
$chromeDriverPath = 'C:\path\to\chromedriver.exe';
$site = 'http://mytestsite';
$seleniumPort = 4445;
$useSelenium = true;
$chromeDriverPathEnvVar = 'webdriver.chrome.driver';
putenv( $chromeDriverPathEnvVar .'='. $chromeDriverPath );
$chromeOptions = new Chrome\ChromeOptions();
$chromeOptions->addArguments( array( '--headless' ) );
$chromeCapabilities = DesiredCapabilities::chrome();
$chromeCapabilities->setCapability( Chrome\ChromeOptions::CAPABILITY, $chromeOptions );
$chromeCapabilities->setCapability( 'loggingPrefs', ['browser' => 'ALL'] );
$selenium = null;
if ($useSelenium) {
$descriptorspec = array(
0 => array('pipe', 'r'), // stdin is a pipe that the child will read from
1 => array('file', __DIR__ . '/selenium_log-' . date('Ymd-His').'_'. $seleniumPort . '-stdout.txt', 'a'), // stdout is a pipe that the child will write to
2 => array('file', __DIR__ . '/selenium_log-' . date('Ymd-His').'_'. $seleniumPort . '-stderr.txt', 'a') // stderr is a file to write to
);
$selenium_cmd = $javaPath .' -D'. $chromeDriverPathEnvVar .'="'. $chromeDriverPath .'" -jar '. $seleniumPath .' -port '. $seleniumPort; // If interested, add .' -debug';
$selenium = proc_open( $selenium_cmd, $descriptorspec, $pipes, null, null, array( 'bypass_shell' => true ) );
$host = 'http://localhost:'. $seleniumPort .'/wd/hub'; // this is the default
$chromeDriver = RemoteWebDriver::create($host, $chromeCapabilities );
} else {
$chromeDriver = Facebook\WebDriver\Chrome\ChromeDriver::start( $chromeCapabilities );
}
$chromeDriver->get( $site );
var_dump( $chromeDriver->manage()->getLog( 'browser' ) );
$chromeDriver->quit(); sleep(1);
$chromeDriver->action(); sleep(1);
$chromeDriver->close();
if ($useSelenium) {
fclose( $pipes[0] );
proc_terminate( $selenium );
#pclose( $selenium );
}
I was banging my head against this for a while- getting an empty array returned from $driver->manage()->getLog('browser');. Then I found this github issue. I changed
$desiredCapabilities->setCapability('loggingPrefs', ['browser'=>'ALL']); to
$desiredCapabilities->setCapability('goog:loggingPrefs', ['browser'=>'ALL']);. The difference was adding in goog: before loggingPrefs.
After that, whammo, $driver->manage()->getLog('browser'); returns a non-empty array =).
I know that I can run a command within another command.
like this example..
$command = $this->getApplication()->find('cache:clear');
$arguments = array();
$input = new ArrayInput($arguments);
$returnCode = $command->run($input, $output);
$text = '';
if ($returnCode != 0) {
$text .= 'successfully...';
}
$output->writeln($text);
But when I trying to run the cache:clear command with their options-
$arguments = array(
'--env=prod' => true
);
I get the following error
[Symfony\Component\Console\Exception\InvalidOptionException]
The "--env=prod" option does not exist.
How can I run this command?
You should use it like:
$arguments = array(
'--env' => 'prod',
);
-- is only needed when passing an option, not an argument.
To make your command able to consider your argument, just use:
$arguments = ['env' => 'prod'];
If it doesn't work, simply use $input->setArgument('env', 'prod');
I have installed youtube-dl on my CentOS 6 / Plesk 10 Dedicated server, and via SSH, everything works like a charm !
The thing is I'm trying to write a php script which takes a POST parameter in containing the URL of the video I want to copy to the server, copy it and then process it with ffmpeg.
I thought I would use the exec() function.
I can get an output if I echo the results of youtube-dl --help, but everytime I ask php to execute a command which actually does something with the video, it returns a status of '1', and outputs nothing.
Any ideas on what I'm doing wrong ?
Here is my php code:
<?php
$result = array();
$status;
$url = $_POST['src'];
$string = 'youtube-dl "'.$url.'" -f 18 -o "/var/www/vhosts/my.virtual.host.net/httpdocs/downloader/downloads/%(id)s.%(ext)s"';
$string2 = 'youtube-dl --help';
exec($string, $result, $status);
echo json_encode(array('status' => $status, 'url_orginal'=>$url, 'url' => $result));
?>
When I execute $string2, I get status: "0" and "url": [youtube-dl help text lines]
But when I execute $string, nothing happens, I get "status": "1" and nothing else, no video is downloaded. I've tried also a simulation with the "-g" parameter, and variants but as soon as youtube-dl has to fetch the video, it breaks.
Thank you in advance !
EDIT
I edited my code so it looks like this :
<?php
$result = array();
$status;
$url = $_POST['src'];
$string = 'youtube-dl "'.$url.'" -f 18 -o "/var/www/vhosts/my.virtual.host.net/httpdocs/downloader/downloads/%(id)s.%(ext)s"';
$string2 = 'youtube-dl --help';
exec($string, $result, $status);
echo json_encode(array('status' => $status, 'url_orginal'=>$url, 'url' => $result, 'command' => $string));
?>
and the result, which I didn't get yesterday now is :
command: "youtube-dl "http://www.youtube.com/watch?v=coq9klG41R8" -f 18 -o "/var/www/vhosts/my.virtual.host.net/httpdocs/downloader/downloads/%(id)s.%(ext)s""
status: 1
url:
0: "[youtube] Setting language"
1: "[youtube] coq9klG41R8: Downloading video info webpage"
2: "[youtube] coq9klG41R8: Extracting video information"
url_orginal: "http://www.youtube.com/watch?v=coq9klG41R8"
Which is weird, considering a) that yesterday I got an empty url[], and that b) even if now I get what apparently looks like a normal youtube-dl return, it only contains the 3 first lines, and I cannot see any video file in the specified path... Any ideas ?
exec reads only stdout, so you're missing the error message on stderr, whatever that may be.
Use the following code to get stderr as well:
$url = 'http://www.youtube.com/watch?v=coq9klG41R8';
$template = '/var/www/vhosts/my.virtual.host.net/httpdocs/downloader/' .
'downloads/%(id)s.%(ext)s';
$string = ('youtube-dl ' . escapeshellarg($url) . ' -f 18 -o ' .
escapeshellarg($template));
$descriptorspec = array(
0 => array("pipe", "r"), // stdin
1 => array("pipe", "w"), // stdout
2 => array("pipe", "w"), // stderr
);
$process = proc_open($string, $descriptorspec, $pipes);
$stdout = stream_get_contents($pipes[1]);
fclose($pipes[1]);
$stderr = stream_get_contents($pipes[2]);
fclose($pipes[2]);
$ret = proc_close($process);
echo json_encode(array('status' => $ret, 'errors' => $stderr,
'url_orginal'=>$url, 'output' => $stdout,
'command' => $string));
Most likely, you don't have permission to write to that directory. To test that theory, check whether
touch /var/www/vhosts/my.virtual.host.net/httpdocs/downloader/downloads/test
works. You can use chmod and chown to change permissions.
I have a few console command in Symfony2 and I need to execute one command from another command with some parameters.
After successfull execution of the second command I need to get the result (as an array for example), not the display output.
How can I do that?
Here you can have a basic command inside a command. The output from the second command can be a json, then you just have to decode the output json to retrieve your array.
$command = $this->getApplication()->find('doctrine:fixtures:load');
$arguments = array(
//'--force' => true
''
);
$input = new ArrayInput($arguments);
$returnCode = $command->run($input, $output);
if($returnCode != 0) {
$text .= 'fixtures successfully loaded ...';
$output = json_decode(rtrim($output));
}
you have to pass the command in the arguments array, and to avoid the confirmation dialog in doctrine:fixtures:load you have to pass --append and not --force
$arguments = array(
'command' => 'doctrine:fixtures:load',
//'--append' => true
''
);
or it will fail with error message “Not enough arguments.”
There is an new Output class (as of v2.4.0) called BufferedOutput.
This is a very simple class that will return and clear the buffered output when the method fetch is called:
$output = new BufferedOutput();
$input = new ArrayInput($arguments);
$code = $command->run($input, $output);
if($code == 0) {
$outputText = $output->fetch();
echo $outputText;
}
I did the following
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\StreamOutput;
$tmpFile = tmpfile();
$output = new StreamOutput($tmpFile);
$input = new ArrayInput(array(
'parameter' => 'value',
));
$command = . . .
$command->run($input, $output);
fseek($tmpFile, 0);
$output = fread($tmpFile, 1024);
fclose($tmpFile);
echo $output;
¡it works!
I understand it's old post and above answers solves the problem with a bit of digging. In Symfony2.7, I had a bit issue making it work, so with above suggestions, I dug a little and have compiled the full answer here. Hope it will be useful for someone.
Using Console command under console command
As an update for Onema's answer, in Symfony 3.4.x (used by Drupal 8),
you also need to set setAutoExit(false),
and the command returns an int(0) if successful.
Here's the updated example that I'm using to script composer commands in php for a Drupal 8.8 project. This gets a list of all composer packages as json, then decodes that into a php object.
<?php
require __DIR__.'/vendor/autoload.php';
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\Console\Input\ArrayInput;
use Composer\Console\Application;
$input = new ArrayInput([
'command' => 'show',
'--format'=>'json',
]);
$output = new BufferedOutput();
$application = new Application();
// required to use BufferedOutput()
$application->setAutoExit(false);
// composer package list, formatted as json, will be barfed into $output
$status = $application->run($input, $output);
if($status === 0) {
// grab the output from the $output buffer
$json = $output->fetch();
// decode the json string into an object
$list = json_decode($json);
// Profit!
print_r($list);
}
?>
The output will be something like this:
stdClass Object
(
[installed] => Array
(
... omitted ...
[91] => stdClass Object
(
[name] => drupal/core
[version] => 8.9.12
[description] => Drupal is an open source content management platform powering millions of websites and applications.
)
... omitted ...
)
)
With the help of Onema's hint Google found the rest of the solution for me here.