Set timeout to a PHP function - php

I have this script
<?php
function get_reverse_dns($Ip)
{
$result = exec("nslookup -n ".escapeshellarg($Ip)." | grep 'name = '");
if(strpos($result,"name =") === false)
{
return "NO REVERSE";
}
else
{
$result = trim($result);
$ExplodedResult = explode("name =",$result);
$ExplodedResult[1] = trim($ExplodedResult[1]);
$ReverseDns = trim($ExplodedResult[1],".");
return $ReverseDns;
}
}
?>
that gives me the reverse dns, now the problem is that sometimes, an IP can have a really long delay, and i want that this script to check it the IP can be "looked up", and if 5 seconds passed and this is not happening, then return false
How can i make that?
I have tried in linux
nslookup --timeout 5 1.1.1.1 | grep 'name = '
timeout 5 nslookup 1.1.1.1 | grep 'name = '
Thanks.

I would use dig:
dig -x ${ip} +time=5 +tries=1 +retry=0 +short
This command will only return the IP address so it will simplify your parsing bit.

You want to check man nslookup that will give you that the command should be:
nslookup -timeout 5 1.1.1.1 | grep 'name = '
You have one too many -'s

Related

how to get the status of the particular process by the shell_exec()?

I want to know the status of the process by passing the name in the command and execute it with the function shell_exec().
I have tried this:
`
$checkProcessStatus = "ps aux | grep <ProcessName>";
$status = shell_exec($checkProcessStatus);
dd($status);
`
I got this result:
`
user 17072 0.0 0.2 166216 33332 pts/3 S+ 11:31 0:00 <ProcessName> artis
user 20397 0.0 0.0 14232 868 pts/3 S+ 11:52 0:00 grep <ProcessName>
`
I want only the Status Like "Running" OR "Sleeping".
Here is the working code:
<?php
$command = 'ps aux';
$result = shell_exec($command);
//split for rows
$processes = explode("\n", $result);
//delete head row
array_shift($processes);
//analyze
foreach ($processes as $rawProcess) {
//beware, command line column may include spaces, that why last group is (.+)
preg_match('/(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(.+)/', $rawProcess,$matches);
//preg match doesn't find anything
if (empty($matches)) {
continue;
}
//is sleeping status
if (strpos($matches[8], 'S') === 0) {
echo $rawProcess;
echo "\n";
continue;
}
//is running status
if (strpos($matches[8], 'R') === 0) {
echo $rawProcess;
echo "\n";
continue;
}
//is not sleeping and not running status
}
You can use $matches[N] for any column.
By the way you can use awk to grep data by status
ps aux | awk 'substr($8,1,1) == "S" || substr($8,1,1) == "R"'
P.S.
Status mean:
D uninterruptible sleep (usually IO)
R running or runnable (on run queue)
S interruptible sleep (waiting for an event to complete)
T stopped by job control signal
t stopped by debugger during the tracing
W paging (not valid since the 2.6.xx kernel)
X dead (should never be seen)
Z defunct ("zombie") process, terminated but not reaped by its parent
Status addition mean
< high-priority (not nice to other users)
N low-priority (nice to other users)
L has pages locked into memory (for real-time and custom IO)
s is a session leader
l is multi-threaded (using CLONE_THREAD, like NPTL pthreads do)
+ is in the foreground process group

Need a way to selectively kill sleeping php processes

I have a website that periodically gets a large number of sleeping php processes. My hosting service sets a limit of 20 concurrent running processes. If it goes over the limit my site goes down with a 503 error.
It is a rare occurrence and doesn't seem to have any correlation to the number of people visiting my site.
As a safeguard I would like to have a cron job with a php script that would kill php processes that have been sleeping for over 10 min.
I have a php function that will kill all sleeping MySql processes that have been sleeping for more than 10 min;
public function kill_sleeping_mysql_processes()
{
$result = $this->db->query("SHOW FULL PROCESSLIST");
foreach($result->result_array() as $row)
{
if ($row['Command'] == "Sleep" && $row['Time'] > 600)
{
$this->db->query("KILL {$row['Id']}")
}
}
}
The question is how can do I do the same with php processes?
I can get a read out of php processes with this code.
exec("ps aux | less", $output);
and I can kill specific php processes with this code if I have the pid;
$pid = 11054;
exec("kill -9 $pid");
But how can I selectively kill php processes that have been sleeping more than 10 min?
I cobbled something together. It is not elegant and is a bit of a hack but it seems to work, although I am going to test it further before putting in a cron job.
public function kill_dormant_php_processes()
{
$output_array = array();
exec("ps aux | grep -v grep", $ps_output);
array_shift($ps_output);
if (count($ps_output) > 0)
{
$i = 0;
foreach ($ps_output as $ps)
{
$ps = preg_split('/ +/', $ps);
$output_array[$i]->pid = $ps[1];
$output_array[$i]->stat = $ps[7];
$output_array[$i]->time = $ps[9];
$i++;
}
}
if( ! empty($output_array))
{
foreach ($output_array as $row)
{
if( $row->stat == 'S' && date('H:i', strtotime($row->time)) > date('H:i', strtotime('00:01')))
{
exec("kill -9 $row->pid");
}
}
}
}
I am sure there must be a better way to do it.
Could someone explain why 00:01 in the read out seems to translate to 6 min?
freedom 6933 6.0 0.1 57040 13040 ? S 16:55 0:01 /usr/local/bin/php53.cgi -c .:/home/freedom/:/etc index.php
As an alternative to the PHP script shared here, you can use the killall command with an "older than" time filter (using the -o option) to kill all those processes.
This command for example will kill all php-cgi processes that have been running for more than 30 minutes:
killall -o 30m /usr/bin/php-cgi

Getting Network Client MAC address, Syntax issue using PhP

Actually the below coding is working fine, if I provide the ip address directly inside the shell_exec()
$mac = shell_exec('arp -a 192.168.0.107');
If, I get the ip of the client from his system and stored in a variable and call the same, as given below,
$mac = shell_exec('arp -a' . escapeshellarg($ip));
The output is not generating.
Here is the Full code:
<?php
$ip = $_SERVER['REMOTE_ADDR'];
$mac = shell_exec('arp -a'. escapeshellarg($ip));
//Working fine when sample client IP is provided...
//$mac = shell_exec('arp -a 192.168.0.107');
$findme = "Physical";
$pos = strpos($mac, $findme);
$macp = substr($mac,($pos+42),26);
if(empty($mac))
{
die("No mac address for $ip not found");
}
// having it
echo "mac address for $ip: $macp";
?>
Please advise, why escapeshellarg($ip) does not work in the shell_exec().
shell_exec('arp '.$ip.' | awk \'{print $4}\'');
Result from Terminal
└── arp 10.1.10.26 | awk '{print $4}'
a4:5e:60:ee:29:19
This is the correct format:
$mac=shell_exec("arp -a ".$ip);
or
$mac=shell_exec("arp -a ".escapeshellarg($ip));
(using the escapeshellarg call)
A space is missing just after the -a in 'arp -a'.escape...
So it turns into arp -a192.168.0.107
This is working for me...
$ip=$_SERVER['REMOTE_ADDR'];
$mac_string = shell_exec("arp -a $ip");
$mac_array = explode(" ",$mac_string);
$mac = $mac_array[3];
echo($ip." - ".$mac);
shell_exec("arp -a ".escapeshellarg($_SERVER['REMOTE_ADDR'])." | grep -o -E '([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}'");

Execute background system command and capture output in a array using PHP

I'm trying to ping a bunch of IPs using PHP/HTML.
<?php
$ip=array("192.10.1.1","192.10.1.2","192.10.1.3","192.10.1.4","192.10.1.5")
$list=count($ip);
$instruction = "";
for ($x=0; $x<$list; $x++)
{
if ($x > 0)
{
$send2_bg =" & ";
}
else
{
$send2_bg = "";
}
$instruction = $instruction.$send2_bg."ping -c 2 -w 1 ". $ip[$x]." | grep -i received | awk '{print $4}'" ;
}
echo $instruction;
$result =exec($instruction);
?>
Expected output array
1 1 0 0 2
But I'm failing to get the output, The instruction is constructed perfectly but after exec(), the output is not as I expect.
exec() just returns the last line of the output
shell_exec() returns all output
Try capturing the output like this:
exec($command, $host, $output);
print_r($output);
The problem is that you are echoing the instruction var see that link - PHP manual
Please reffer to the parameter output and echo that one instead the instruction var.

Parsing grep output

I'm trying to make a server manager and here is what I have so far:
<?php
$COMMAND = shell_exec('ps ax --format command | grep skulltag');
$arr = explode("./",$COMMAND);
$text = shell_exec('pgrep -u doom');
$arrtext = preg_split('/\s+/', $text);
for( $i = 1; $i < count($arr); $i++ ) {
echo $i,". PROCESS ID ",$arrtext[$i]," Command issued: ",$arr[$i];
echo '<br>';
}
?>
As you can see, I'm separating the $COMMAND string with ./ (file execution). However, for some reason at the end of the list there's this:
sh -c ps ax --format command | grep skulltag grep skulltag
Here is the full output for reference:
PROCESS ID 4793 Command issued: skulltag-server
PROCESS ID 4956 Command issued: skulltag-server -port 13000
PROCESS ID 4958 Command issued: skulltag-server -port 13001 sh -c
ps ax --format command | grep skulltag grep skulltag
What would be the easiest and most effective way to get rid of that line, and how would I do it? Thanks.
Change this:
ps ax --format command | grep skulltag
To this:
ps ax --format command | grep [s]kulltag
That way, the grep command itself contains the string '[s]kultag', which is not matched by the grep regular expression '[s]kultag'.
Also, two suggestions: 1. there's no guarantee that your initial ps | grep and your later pgrep will line up. Instead, use a single pgrep:
pgrep -afl skulltag
And 2. your for loop starts with 1, which will skip the process in arr[0].
Your php could be rewritten something like this:
$processes = explode("\n", shell_exec('pgrep -afl skulltag'));
foreach($processes as $i => $process) {
($pid, $command) = explode(' ',$process,2);
echo $i+1,". PROCESS ID ",$pid," Command issued: ",$command;
echo '<br>';
}
My quick and dirty solution is to append | grep -v grep to the command.

Categories