I login to AS400 and go to QSHELL(STRQSH). After that I pasted the following command and run it in QSHELL
system "IVIEW/PRTDISTL APPNAME(MYJOBLOG) STMF(TEST_89.PDF) HOLD(*NO)"
It works. But when I execute the above command using PHP script as the follow
$cmd = "IVIEW/PRTDISTL APPNAME(MYJOBLOG) STMF(TEST_89.PDF) HOLD(*NO)";
$cmd = 'system "' . $cmd . '"';
$output = array();
exec ($cmd, $output , $retVal);
echo "return value code: " . $retVal;
It returns error code of 255. Please help me how to fix this issue. Thanks
Try the PHP Toolkit for i5/OS. There is a older Redbook that describes it: http://www.redbooks.ibm.com/redbooks/pdfs/sg247327.pdf
An example from there:
<HTML>
<?php
/* Connect to server */
$conn = i5_connect("localhost", "PHPUSER", "MYPASSWORD");
if (!$conn)
die("<br>Connection using \"localhost\" with USERID and PASSWORD failed. Error
number =".i5_errno()." msg=".i5_errormsg())."<br>";
else
echo "<br>Connection using \"localhost\" with USERID and PASSWORD OK!<br>\n";
/* Call Retrieve Network Attributes command */
$ret = i5_command("rtvneta", array(), array("sysname" => "sysn", "lclnetid"=>"lclnet"));
if (!$ret) die("<br>rtvneta command failed. errno=".i5_errno()."
msg=".i5_errormsg());
print "<h1><b>Results of \"rtvneta\" command </b></h1><br>" ;
print "System Name : $sysn<br>" ;
print "Local Net ID : $lclnet<br>" ;
/* Close connection */
i5_close($conn);
?>
</HTML>
I see two pontential problems:
PHP runs in PASE, not in QShell. Try to manually run your call from QP2TERM.
User rights. Make sure QTMHHTTP (or whatever user runs PHP) has the apropriate rights to the program you try to call.
You can check for further information in stdout, which you should have in $output, and your PHP-server joblog as mentioned at IBM i information center (possibly needing the flag 'system -K').
Related
Using PHP, I need to periodically execute a remote command on a Draytek 2925 router using SSH.
I can already connect to the router using the standard "ssh" command on Linux, but after authenticating I am getting "PTY allocation request failed on channel 0". However despite that message, I can still send commands.
When I try doing the same with PHP, I am getting 1 of 2 results and neither of which is returning the results I need.
My code is as follows:
<?
if (!($connection = ssh2_connect('my.router.local', 22)))
die('CONN');
else if (!ssh2_auth_password($connection, 'admin', 'password'))
die('AUTH');
else
{
$stream = ssh2_exec($connection, 'sys version');
stream_set_blocking($stream, true);
$stream_out = ssh2_fetch_stream($stream, SSH2_STREAM_STDIO);
echo stream_get_contents($stream_out);
exit();
}
?>
The PHP fails at ssh2_exec(). If I specify the 3rd argument (pty), I get this result:
Warning: ssh2_exec(): Failed allocating 1 pty at 80x25 characters
However, not specifying the 3rd argument results in:
Warning: ssh2_exec(): Unable to request command execution on remote host
Even if I type #ssh2_exec(), I don't get a warning, but I don't get a result either.
If PHP is a no-go, I tried using sshpass in the same way, but that results in the following:
# sshpass -f sshpwd -v ssh admin#my.router.local 'sys version'
SSHPASS searching for password prompt using match "assword"
SSHPASS read: admin#my.router.local's password:
SSHPASS detected prompt. Sending password.
SSHPASS read:
exec request failed on channel 0
#
I ultimately just need to authenticate, send a command and return the result. Is there anything I am doing wrong or is there a simpler way?
I have resolved my query by using TELNET instead. Yes it's not secure like SSH, but since it's being used internally over the LAN, it doesn't matter.
For anyone interested, I used Net_Telnet and the following code:
<?php
require_once "Net/Telnet.php";
$router = 'my.router.local';
$password = 'password';
try
{
$t = new Net_Telnet($router);
$t->connect();
$t->login([
'login_prompt' => 'Account:',
'login_success' => ' User login successful, expired time is "Unlimited".',
'login_fail' => '% Access denied',
'login' => 'admin',
'password' => $password,
'prompt' => "{$router}>",
]
);
echo $t->cmd('sys version');
$t->disconnect();
// catch any buffered data
echo $t->get_data();
echo "\n";
} catch (Exception $e)
{
echo "Caught Exception ('{$e->getMessage()}')\n{$e}\n";
}
exit();
?>
Which results in:
# php -f telnet.php
sys version
Router Model: Vigor2925n Version: 3.8.4 English
Profile version: 3.0.0 Status: 1 (0x48245e4c)
Router IP: 0.0.0.0 Netmask: 255.255.255.0
Firmware Build Date/Time: Dec 15 2016 17:26:01
Router Name: my.router.local
Revision: 61327 V384_2925
>
#
I am trying to take the backup of postgresql database using php. If I try it in the command prompt using the following then it is working. But if I try it using exec() then an empty file is generated.Also the php script gets executed infinitely.
pg_dump -U postgres test > D:/backup.sql
The following code works.
putenv("PGPASSWORD=postgres");
$dumpcmd = array("pg_dump", "-i", "-U", escapeshellarg("postgres"), "-F", "c", "-b", "-v", "-f", escapeshellarg("D:/backup4.sql"), escapeshellarg("test"));
exec( join(' ', $dumpcmd), $cmdout, $cmdresult );
putenv("PGPASSWORD");
if ($cmdresult != 0)
{
# Handle error here...
echo "error";
}
I am running PHP vc9 NTS 5.3.28 on Windows Server 2003 Standard 32bit with phpseclib 0.3.6. I am trying to creating a script that will connect to a Palo Alto Networks firewall and execute a command to hash a password. I have the following code:
<?php
include 'Net/SSH2.php';
define('NET_SSH2_LOGGING', NET_SSH2_LOG_COMPLEX);
$ssh = new Net_SSH2('hostname');
echo ">Logging in...\n";
if (!$ssh->login('user', 'password')) {
exit('Login Failed');
}
echo ">Reading login results...\n";
/*echo $ssh->exec('request password-hash password test123');*/
$output = $ssh->read('user#PA-3020>');
echo $output . "\n";
echo ">Writing request...\n";
$ssh->write("request password-hash password test123\n");
$ssh->setTimeout(10);
echo ">Reading result...\n";
$output = $ssh->read('/^\$1\$.*$/', NET_SSH2_READ_REGEX);
echo $output . "\n";
echo ">Done.\n";
file_put_contents ('E:\PHP53\ssh2.log', $ssh->getLog());
?>
I have two problems with the above code:
If I leave out the setTimeout(10) then the code never exists the next $ssh->read. If I have it in, then the code exists only after the timeout but does return results.
The results it returns are including a bunch of stuff that shouldn't be there:
?[Kuser#PA-3020> request password-hash password test123
?[?1h?=?[24;1H?[K
$1$dgkhwrxe$kddYFmKCq9.zfiBKPAyN61
?[24;1H?[K?[?1l?>user#PA-3020>
I only want the line that starts with $1$ (line 3 above). I figure it has something to do with the regex but I can't figure out what.
If I run the command interactively with PuTTY I get the following:
user#PA-3020> request password-hash password test123
$1$pxqhdlco$MRsVusWtItC3QiMm4W.xZ1
user#PA-3020>
UPDATE:
As per suggestions from neubert below, replacing the line with $output = $ssh->read... with the following code works:
$output = $ssh->read('/\$1\$.*/', NET_SSH2_READ_REGEX);
$output = preg_replace('/.*\$1\$/s','\$1\$', $output);
The results it returns are including a bunch of stuff that shouldn't
be there:
?[Kuser#PA-3020> request password-hash password test123
?[?1h?=?[24;1H?[K $1$dgkhwrxe$kddYFmKCq9.zfiBKPAyN61
?[24;1H?[K?[?1l?>user#PA-3020>
Those are ANSI escape codes. You can use File_ANSI to remove them. More info:
http://phpseclib.sourceforge.net/ssh/examples.html#top
Anyway, my guess would be that you need to redo your regex. eg.
$output = $ssh->read('/^\$1\$.*$/', NET_SSH2_READ_REGEX);
Instead of doing that do this:
$output = $ssh->read('/\$1\$/', NET_SSH2_READ_REGEX);
The thing is... ^ matches at the start of the line and $ matches at the end. Usually when you do $ssh->write(...) the command is echo'd back to you and then there's a new line and then you get your output back. So that'd prevent ^ from working. And as for the $ at the end.. well per your own example $1$ doesn't occur at the end of a line. So that's why your code isn't working.
Is there a PHP functionallity same as read -i in BASH so that a script can prompt the user and provide a default answer like this:
Are you doing ok? (yes/no): yes
Where "yes" is the default answer provided by the script, which the user can erase and input another.
The readline function does not seem to have what it takes. Is there any other way to do this?
Using a stream does not seem to work either:
<?php
echo "Are you doing ok? (yes/no): ";
$in = fopen('php://stdin', 'rw+');
fputs($in, 'yes'); // should be the default?
$answer = fgets($in);
fclose($in);
echo "\nYou entered: {$answer}\n";
Whatever is in written by the fputs($in, 'yes'); line is ignored:
Are you doing ok? (yes/no): yes
You entered:
Am I using the stream incorrectly? Or maybe there is some other way to achive the default value?
EDIT:
Maybe I simlified the example to much. The real issue is not a simple yes/no prompt - this is just an example. Let me emphasize again: I'm aiming for providing exactly the same functionallity as the read -i BASH command. The $answer in my specific case holds an URL, so I would like for the user to be provided with the first part of the url (scheme, host, port), so he can add/edit the rest (path, query), fragment. Like this:
Enter url: http://www.example.com/foo/
now the user complement the path with bar/baz and we get:
You entered: http://www.example.com/foo/bar/baz
But on the other hand the user also should have the option to erase the first part of the url and provide completely different string:
Enter url: ftp://www.my-super-specific-domain.com/foo/bar
There's no built in way of doing this because writing some code that does it is quite straight forward:
function writeQuestion($question, $answers)
{
echo $question . ' (' . implode('/', $answers) . '): ' . PHP_EOL;
}
function readAnswer($possibleAnswers, $defaultAnswer)
{
$in = fopen('php://stdin', 'rw+');
$answer = trim(fgets($in));
if(!in_array($answer, $possibleAnswers))
{
return $defaultAnswer;
}
return $answer;
}
$question = 'Are you doing ok?';
$answers = array('yes', 'no');
$defaultAnswer = 'yes';
writeQuestion($question, $answers);
$answer = readAnswer($answers, $defaultAnswer);
You can wrap standard bash read for prefilled/populated edit and call it from you main php cli script
bash script named xreadline:
#! /bin/bash
IFS="";read -r -p "$1" -i "$2" -e STRING;echo "$STRING"
main php cli script:
#!/usr/bin/php
<?php
function xreadline ($prompt,$prefill)
{
$on = exec ('./xreadline "'.$prompt.'" "'.$prefill.'"');
return $on;
}
$answer = xreadline ('Your answer: ', 'xyz');
echo $answer;
.....
This approach fully supports UTF8 instead of native PHP readline.
Comment messed my code so here is standalone php cli file with function call to "read" command.
Little bit tricky, but hopefully will work as supposed to. :-)
#!/usr/bin/php
<?php
function xreadline ($prompt,$prefill)
{
return exec ('/bin/bash -c \'read -r -p "'.$prompt.'" -i "'.$prefill.'" -e STRING;echo "$STRING";\'');
}
echo "Prompt test :\n";
$output = xreadline ("edit this prefilled prompt: ","prefilled stuff");
echo "\n";
echo $output;
I have a PHP script that gets passed the MySQL connection details of a remote server and I want it to execute a mysqldump command. To do this I'm using the php exec() function:
<?php
exec("/usr/bin/mysqldump -u mysql-user -h 123.145.167.189 -pmysql-pass database_name > /path-to-export/file.sql", $output);
?>
When the right login details are passed to it, it'll work absolutely fine.
However, I'm having trouble checking if it executes as expected and if it doesn't finding out why not.
The $output array returns as empty, whereas if I run the command directly on the command line a message is printed out telling me the login failed. I want to capture such error messages and display them. Any ideas on how to do that?
You should check the third parameter of exec function: &$return_var.
$return_var = NULL;
$output = NULL;
$command = "/usr/bin/mysqldump -u mysql-user -h 123.145.167.189 -pmysql-pass database_name > /path-to-export/file.sql";
exec($command, $output, $return_var);
By convention in Unix a process returns anything other than 0 when something goes wrong.
And so you can:
if($return_var) { /* there was an error code: $return_var, see the $output */ }
The solution I found is to run the command in a sub-shell and then output the stderr to stdout (2>&1). This way, the $output variable is populated with the error message (if any).
i.e. :
exec("(mysqldump -uroot -p123456 my_database table_name > /path/to/dump.sql) 2>&1", $output, $exit_status);
var_dump($exit_status); // (int) The exit status of the command (0 for success, > 0 for errors)
echo "<br />";
var_dump($output); // (array) If exit status != 0 this will handle the error message.
Results :
int(6)
array(1) { [0]=> string(46) "mysqldump: Couldn't find table: "table_name"" }
Hope it helps !
Because this line redirect the stdout output > /path-to-export/file.sql
try this,
<?php
exec("/usr/bin/mysqldump -u mysql-user -h 123.145.167.189 -pmysql-pass database_name", $output);
/* $output will have sql backup, then save file with these codes */
$h=fopen("/path-to-export/file.sql", "w+");
fputs($h, $output);
fclose($h);
?>
I was looking for the exact same solution, and I remembered I'd already solved this a couple of years ago, but forgotten about it.
As this page is high in Google for the question, here's how I did it:
<?php
define("BACKUP_PATH", "/full/path/to/backup/folder/with/trailing/slash/");
$server_name = "your.server.here";
$username = "your_username";
$password = "your_password";
$database_name = "your_database_name";
$date_string = date("Ymd");
$cmd = "mysqldump --hex-blob --routines --skip-lock-tables --log-error=mysqldump_error.log -h {$server_name} -u {$username} -p{$password} {$database_name} > " . BACKUP_PATH . "{$date_string}_{$database_name}.sql";
$arr_out = array();
unset($return);
exec($cmd, $arr_out, $return);
if($return !== 0) {
echo "mysqldump for {$server_name} : {$database_name} failed with a return code of {$return}\n\n";
echo "Error message was:\n";
$file = escapeshellarg("mysqldump_error.log");
$message = `tail -n 1 $file`;
echo "- $message\n\n";
}
?>
It's the --log-error=[/path/to/error/log/file] part of mysqldump that I always forget about!
As exec() is fetching just stdout which is redirected to the file, we have partial or missing result in the file and we don't know why. We have to get message from stderr and exec() can't do that. There are several solutions, all has been already found so this is just a summary.
Solution from Jon: log errors from mysqldump and handle them separately (can't apply for every command).
Redirect outputs to separate files, i.e. mysqldump ... 2> error.log 1> dump.sql and read the error log separately as in previous solution.
Solution from JazZ: write the dump as a subshell and redirect stderr of the subshell to stdout which can php exec() put in the $output variable.
Solution from Pascal: better be using proc_open() instead of exec() because we can get stdout and stderr separately (directly from pipes).
write below code to get the database export in .sql file.
<?php exec('mysqldump --user=name_user --password=password_enter --host=localhost database_name > filenameofsql.sql'); ?>