-
-
Save mauris/11375869 to your computer and use it in GitHub Desktop.
<?php | |
function runCommand () | |
{ | |
$command = 'php artisan queue:listen > /dev/null & echo $!'; | |
$number = exec($command); | |
file_put_contents(__DIR__ . '/queue.pid', $number); | |
} | |
if (file_exists(__DIR__ . '/queue.pid')) { | |
$pid = file_get_contents(__DIR__ . '/queue.pid'); | |
$result = exec('ps | grep ' . $pid); | |
if ($result == '') { | |
runCommand(); | |
} | |
} else { | |
runCommand(); | |
} |
@di5abled how this function will be called?
or i just have to enqueue my cron jobs and it will run automatically?
Do you have an adaptation of the queue ensurer that will work on a windows server that does not have grep installed?
if exec function is disable you can use this code
$schedule->call(function () {
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
);
$runCommand = false;
$queueFile = storage_path('queue.pid');
if (file_exists($queueFile)) {
$pid = intval(file_get_contents($queueFile));
$process = proc_open("ps -p $pid --no-heading | awk '{print $1}'", $descriptorspec, $pipes);
$result = '';
if (is_resource($process)) {
$result = stream_get_contents($pipes[1]);
fclose($pipes[1]);
}
if ($result == '') {
$runCommand = true;
}
} else {
$runCommand = true;
}
if ($runCommand) {
$dir = base_path() . DIRECTORY_SEPARATOR;
$command = "php {$dir}artisan queue:listen --timeout=60 --tries=1 > '/dev/null' 2>&1 & echo $!";
$process = proc_open("$command", $descriptorspec, $pipes, null, ["register_argc_argv" => "on"]);
$number = '';
if (is_resource($process)) {
$number = stream_get_contents($pipes[1]);
fclose($pipes[1]);
}
file_put_contents($queueFile, $number);
}
});
This sounds like a good solution:
// Using `queue:work` for Laravel 5.4
$schedule->command('queue:work')->everyMinute()->withoutOverlapping();
Anyone see any issue with it?
Nvm, it doesn't background the queue:work
like this snippet does.
A made a simple solution for this (Laravel 5.5 dev).
I created a new function, that checks if the process is running.
Then, a simple if-condition arround the command does the thing
// start the queue daemon, if its not running
if ( !$this->osProcessIsRunning('queue:work') ) {
$schedule->command('queue:work') ->everyMinute();
}
I put the new function right in app/Console/Commands/Kernel.php:
/**
* checks, if a process with $needle in the name is running
*
* @param string $needle
* @return bool
*/
protected function osProcessIsRunning($needle)
{
// get process status. the "-ww"-option is important to get the full output!
exec('ps aux -ww', $process_status);
// search $needle in process status
$result = array_filter($process_status,
function($var) use ($needle)
{ return strpos($var, $needle); });
// if the result is not empty, the needle exists in running processes
if (!empty($result)) {
return true;
}
return false;
}
Edit: Execution time on my dev-machine is 3-4ms.
Thanks kohlerdominik!,
It's working perfectly.
@kohlerdominik solution work's great! Thanks!
@kohlerdominik perfect solution. Thanks!
What's the purpose of & echo $!
here?
For shared hosted with disabled exec functions, I made a shell script.
Cron job:
* * * * * cd /path/to/public_html && /usr/bin/sh artisan.call.sh >> /dev/null 2>&1
How work
- Check for folder
/storage/queue.lock/
- If not exists, call
artisan queue:work
and create the folder, otherwise do nothing. - Check for file
/storage/.queue-restart
, if exists, runartisan queue:restart
and remove folder/storage/queue.lock/
When run artisan queue:restart
the script must exit and auto remove queue.lock folder, next time call artisan queue:work
.
#!/bin/bash
FULL_PATH_TO_SCRIPT="$(realpath "$0")"
SCRIPT_DIRECTORY="$(dirname "$FULL_PATH_TO_SCRIPT")"
LOCKFILE="$SCRIPT_DIRECTORY/storage/queue.lock"
LOGFILE="$SCRIPT_DIRECTORY/storage/logs/queue.log"
QUEUE_RESTART_FILE="$SCRIPT_DIRECTORY/storage/logs/.queue-restart"
d=$(date '+%F %T')
log()
{
echo '=============================================================================================' >> "${LOGFILE}"
echo "$d" >> "${LOGFILE}"
if [ "$1" ]; then
echo "$1" >> "${LOGFILE}"
fi
}
clean_log()
{
truncate -s 0 "${LOGFILE}"
}
remove_lock()
{
log "Removing lock file $LOCKFILE… exiting"
rmdir "$LOCKFILE"
}
another_instance()
{
log "Lock file $LOCKFILE exists… exiting"
exit 1
}
run_artisan()
{
if [ "$1" ]; then
(php ${SCRIPT_DIRECTORY}/artisan $1)
fi
}
if ! mkdir "${LOCKFILE}" 2>/dev/null; then
another_instance
exit 1
fi
if [ -f "${QUEUE_RESTART_FILE}" ]; then
rm "$QUEUE_RESTART_FILE"
log "restarting queue"
run_artisan "queue:restart"
remove_lock
exit 1
fi
trap remove_lock QUIT INT TERM EXIT
clean_log
log "runing php \"${SCRIPT_DIRECTORY}/artisan queue:work"\"
run_artisan "queue:work"
@alvaro-canepa thanks this work me
I also need the shell-script variant... pgrep
allows to use it without the pid file.
However you can only run one instance of php artisan queue:work
I use pgrep
to only search for the artisan queue:work
since my provider uses an alias for php.
#!/bin/bash
# Check if "artisan queue:work" is running
if pgrep -f "artisan queue:work" > /dev/null
then
echo "queue:work is already running."
exit 1
else
echo "Starting queue:work..."
nohup php artisan queue:work > /dev/null 2>&1 &
echo "queue:work started."
fi
@CodeAndWeb looks nice, more clean than my code!
Thanks to share
Improved the code a little bit and it seems to work fine for me in my current L 5.2: