The right-way to run shell commands or scripts right from the PHP script.
The package is exlcusively designed to be used with Laravel framework, but can also be used with Core PHP along with Laravel's Eloquent
Click to watch playlist on YouTube:
The package can be installed easily using Composer by executing the following command:
composer require adnanhussainturki/unix-screen-php
- Create model name
Process
using commandphp artisan make:model Process
- Create a new migration using command
php artisan make:migration create_process_table
- Use the following code for migration:
Schema::create('processes', function (Blueprint $table) { $table->id(); $table->string("slug")->unique(); $table->integer("timeout")->default(30); $table->integer("exitcode")->nullable(); $table->json("data"); $table->boolean("closed")->default(false); $table->boolean("success")->nullable(); $table->dateTime("started_at"); $table->bigInteger("started_at_unix"); $table->text("remark")->nullable(); $table->timestamps(); });
The package two modes of execution of commands or scripts:
-
Synchronous Good for running short time-taking commands like
ls
oruname
etc. Running the command or shell script and wait until the execution is completed. This method is NOT RECOMMENDED as it may invoke PHP timeout errors or Webserver timeout errors. Along with these, this method is not also so good for user experience. -
Asynchronous (Recommended) Great for running time-taking command or scripts like
top
orcp
ormv
etc.
<?php
use myPHPnotes\Screen;
$screen = new Screen(storage_path("screen"), new \App\Models\Process());
<?php
use myPHPnotes\Screen;
$screen = new Screen(storage_path("screen"), new \App\Models\Process());
$command = "cp -r /etc/ ~/etc/";
$timeout = 30;
$arguments = [];
$identifier = "myFirstAsynchronouslyRunningCommand"; # Can be null, to use the autogenerated
$screen->executeCommand($request->command, $arguments, $identifier, $timeout);
<?php
use myPHPnotes\Screen;
$screen = new Screen(storage_path("screen"), new \App\Models\Process());
$command = "cp -r /etc/ ~/etc/";
$timeout = 30;
$arguments = [];
$identifier = "myFirstSynchronouslyRunningCommand"; # Can be null, to use the autogenerated
$screen->executeCommandNow($request->command, $arguments, $identifier, $timeout);
<?php
use myPHPnotes\Screen;
$screen = new Screen(storage_path("screen"), new \App\Models\Process());
$script = "
echo "Welcome" $1
useradd john -m
exitcode=$? // Needs to be set to define the exit code for the whole script
touch ~/john/happy
";
// Save the script to temporary file
$filename = "shell_script_".time()."_".md5(random_bytes(1));
$temp_file_path = storage_path("screen/temp/{$filename}.sh");
file_put_contents($temp_file_path, $script);
$timeout = 30;
$arguments = ["Admin"];
$identifier = "myFirstAsynchronouslyRunningScript"; # Can be null, to use the autogenerated
$screen->executeFile($temp_file_path, $arguments, $identifier, $timeout);
<?php
use myPHPnotes\Screen;
$screen = new Screen(storage_path("screen"), new \App\Models\Process());
$script = "
echo "Welcome" $1
useradd john -m
exitcode=$? // Needs to be set to define the exit code for the whole script
touch ~/john/happy
";
// Save the script to temporary file
$filename = "shell_script_".time()."_".md5(random_bytes(1));
$temp_file_path = storage_path("screen/temp/{$filename}.sh");
file_put_contents($temp_file_path, $script);
$timeout = 30;
$arguments = ["Admin"];
$identifier = "myFirstSynchronouslyRunningScript"; # Can be null, to use the autogenerated
$screen->executeFileNow($temp_file_path, $arguments, $identifier, $timeout);
The heartbeat()
function Screen
object must be called every minute (or less). This heartbeat()
call will check and updates the running processes for their exit code and timeouts:
<?php
$screen = new Screen(storage_path("screen"), new \App\Models\Process());
$screen->heartbeat();
You may use the following code in your Laravel command:
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Helpers\Screen;
class Heartbeat extends Command
{
protected $signature = 'screen:heartbeat';
protected $description = 'Command to check and update the status of the processes';
public function __construct()
{
parent::__construct();
}
public function handle()
{
for ($i=0; $i < 5; $i++) {
Screen::get()->heartbeat();
sleep(1);
}
return 0;
}
}
Kernel.php
$schedule->command('screen:heartbeat')->everyMinute();
Make sure to have your Laravel Task Scheduling correctly setup.
-
Create a fork, make changes and send a pull request.
-
Raise a issue
Licensed under MIT.