0

I have a CSV file that sits on a Raspberry PI and outputs:

2018-03-22 12:43:21,NM_Test.h264,-2

On my host server I have a PHP script that takes the output from the CSV file and displays it as a HTML table on my webpage:

$command = "ssh -p 97 -i /var/www/html/test.rsa [email protected] tail -1 /var/log/playlog.csv";
$output = exec($command);
$array = explode(',',$output);

echo '<div class="container"><table class="table table-striped">
 <tr>
 <th>Status</th>
 <th>Name</th>
 <th>Date/Time</th>
 <th>Playing</th>
 <th>Error</th>
 </tr>
 <tr>
 <td>';
 if(in_array('0', $array, true)){
  echo '<div id="circleGreen"></div>';
 }

 if (in_array('-2', $array, true)){
  echo '<div id="circleRed"></div>';
 }
 echo'</td>
 <td>Guildford test</td>
 <td>'.$array[0].'</td>
 <td>'.$array[1].'</td>
 <td>';

This method works for one SSH connection, but how can I run the SSH command multiple times for connecting to different PIs?

I thought about creating a txt file and saving each SSH command in there, and then have my PHP script read/execute each command line by line:

// example txt file 
ssh -p 97 -i test.rsa [email protected] 
ssh -p 97 -i test2.rsa [email protected] 
// and so on..
// only the rsa key name & IP address changes

But I'd like a more efficient solution to my problem.

Update

As recommended I used the phpsec library to SSH onto the PI:

<?php
include('Net/SSH2.php');
include('phpseclib1.0.10/Crypt/RSA.php');

$ssh = new Net_SSH2('192.xxx.xxx.xxx', 97);
$key = new Crypt_RSA();
$key->loadKey(file_get_contents('test.rsa'));

if (!$ssh->login('pi', $key)){
 exit ('Login Failed');
}

echo $ssh->exec('ls -la');
?>

But by doing so I still have to type the IP address as well as the RSA key name. I'd like a solution that allows me to quickly ssh into multiple PIs and execute the exec command.

One possible solution I can think of is allowing my script to read the known_hosts file? Is that possible?

7
  • I would suggest using PHPSecLib2.0, it's way nicer then anything else for SSH (sFTP) IMO> Commented Apr 1, 2018 at 13:14
  • Could you kindly show me an example on how I can use it? There's not much documentation on it Commented Apr 1, 2018 at 13:35
  • There is plenty of documentation you just have to know where to look Like HERE It's about 1000x easier to use then the ssh2 extension. Also one problem with exec is that its not an interactive shell, each command is stateless by itself. you have to/could try to use ssh2 extension and last I knew it was broken for windows. Commented Apr 1, 2018 at 14:09
  • As a bonus, it also does AES SSL (like making self singed certs) and many other cryptographic things. The only thing I find it lacking in is no PGP encryption, but than again there isn't really any easy to use libraries for that.. Commented Apr 1, 2018 at 14:12
  • Thank you for your detailed response and for the link. I managed to get phpseclib woking! I will update my answer so you can see what I did Commented Apr 1, 2018 at 14:52

1 Answer 1

2

This is what I would do... (make my own config file)

//you don't need the ( ) for include/require
//without these files it wont work, should be require then. Classes only need be included 1 time
require_once 'Net/SSH2.php';
require_once 'phpseclib1.0.10/Crypt/RSA.php';
//when you include/require like this it puts the content into the variable
//when that content is a PHP array, it puts it in the variable. This needs to be included each time the script is ran
$config = require 'config.php';
$log = 'logfile.txt';

if(is_array($config)){
    foreach($config as $cred){
        $ssh = new Net_SSH2($cred['ip'], $cred['port']); //i think this is port?
        $key = new Crypt_RSA();
        $key->loadKey($cred['key']);

        if (!$ssh->login('pi', $key)){
             //logging with file_put_contants, Append mode, exclusive lock is more race condition safe then an open file handle.
            file_put_contants($log, "[".date('Y-m-d H:i:s')."]Login Failed for {$cred['ip']}\n", FILE_APPEND|LOCK_EX);
            continue;
            //or you can echo it, but you don't want to kill the whole thing if one fails /maybe?
        }
        //echo or save to file etc.
        echo $ssh->exec('ls -la');
    }
}

Then in config.php

return [
    [
        "ip" : "127.0.0.1",
        "port": 97,
        "key" : 'ssh-dss AAAAB3NzaC1kc3MAA...c3=',
    ]
    [ ... ]
];

You can even modify the config file programmatically by doing something like this

  file_put_contants('config.php', '<?php'."\nreturn ".var_export($config,true).";\n");

The var_export function outputs in a PHP compatible format, ie. syntactically correct. Then the second argument of it is return as string. So this converts the array to a string that is the same format as a valid PHP array. Then it's pretty trivial to add <?php and the return and then the ending ; and save it.

Obviously, I wouldn't suggest saving any "end User" input this way. And you will probably want to prevent access to this file. (eg. put outside the webroot)

Sign up to request clarification or add additional context in comments.

1 Comment

Sure, no problem

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.