Używać PHP do tworzenia, edytowania i usuwania zadań crontab?

116

Czy można używać PHP do tworzenia, edycji i usuwania zadań crontab?

Wiem, jak wyświetlić listę bieżących zadań crontab użytkownika Apache:

$output = shell_exec('crontab -l');
echo $output;

Ale jak dodać zadanie crona w PHP? 'crontab -e' po prostu otworzy edytor tekstu i będziesz musiał ręcznie edytować wpisy przed zapisaniem pliku.

A jak usunąć zadanie cron za pomocą PHP? Ponownie musisz to zrobić ręcznie przez 'crontab -e'.

Z takim ciągiem zadań:

$job = '0 */2 * * * /usr/bin/php5 /home/user1/work.php';

Jak dodać go do listy zadań crontab w PHP?

datasn.io
źródło
2
możliwy duplikat zadań Crona przy użyciu php i kilku innych
Gordon
14
(wskazówka) plik
Gordon
1
@Gordon, dzięki. Wiem, że wszystko jest plikiem, ale czy przechowują zadania crontab na tej samej ścieżce w różnych dystrybucjach? Dodatkowo musiałby uzyskać użytkownika Apache, takiego jak dane www, i mieć uprawnienia roota?
datasn.io
Nie jestem pewien, czy ścieżka zmienia się w dystrybucjach, ale robisz dobrze, aby ścieżka była konfigurowalną wartością w kodzie i ustawiała ją w czasie wykonywania. Jeśli chodzi o użytkownika i uprawnienia: każdy użytkownik może mieć tabelę crontab, która uruchamia zadania z prawami przypisanymi do tego użytkownika, więc jest to indywidualne dla konfiguracji systemu.
Gordon
Zobacz także stackoverflow.com/q/3186471/632951
Pacerier

Odpowiedzi:

133

Użycie polecenia crontab

usage:  crontab [-u user] file
        crontab [-u user] [ -e | -l | -r ]
                (default operation is replace, per 1003.2)
        -e      (edit user's crontab)
        -l      (list user's crontab)
        -r      (delete user's crontab)
        -i      (prompt before deleting user's crontab)

Więc,

$output = shell_exec('crontab -l');
file_put_contents('/tmp/crontab.txt', $output.'* * * * * NEW_CRON'.PHP_EOL);
echo exec('crontab /tmp/crontab.txt');

Powyższe może być używane zarówno do tworzenia, jak i edycji / dołączania, pod warunkiem, że użytkownik ma odpowiednie uprawnienia do zapisu plików.

Aby usunąć zadania:

echo exec('crontab -r');

Zwróć również uwagę, że Apache działa jako konkretny użytkownik i zwykle nie jest to root, co oznacza, że ​​zadania cron mogą być zmieniane tylko dla użytkownika Apache, chyba że nadano mu crontab -uuprawnienia użytkownika Apache.

ajreal
źródło
4
Czy „crontab -r” nie usunie wszystkich zadań użytkownika? Czy istnieje sposób na usunięcie określonej linii zadania w tabelach crontab użytkownika? Ładowanie, wyszukiwanie, a następnie usuwanie znalezionej linii wydaje się być jedynym sposobem.
datasn.io
3
Możesz użyć potoków zamiast pisać plik tymczasowy
realmfoo
7
Niezłe rozwiązanie, ale shell_exec('crontab -l')zwróci tylko ostatnią linię. Użyłem exec('crontab -l', $output). Następnie imploduj tablicę wyjściową $ w łańcuch (z \ n jako klejem).
David Fairbanks,
1
@Rahul jeśli dostawcy serwera nie zapewniają powłoki poleceń takich jak system(), passthru(), shell_exec()i exec()spróbuj za pomocą panelu sterowania, który pochodzi z gospodarzem, takie jak cPanel lub Plesk.
Raptor,
3
spowoduje to dołączanie tego samego zadania za każdym razem do pliku. (zaznaczone) Czy istnieje sposób, aby najpierw usunąć pasujące oferty pracy, a następnie napisać nowe?
RT
20

Niedawno przygotowaliśmy mini projekt (PHP> = 5.3) do zarządzania plikami cron do zadań prywatnych i indywidualnych. To narzędzie łączy i zarządza plikami cron, dzięki czemu można ich używać, na przykład w ramach projektu. Dostępne testy jednostkowe :-)

Przykład z wiersza poleceń:

bin/cronman --enable /var/www/myproject/.cronfile --user www-data

Próbka z API:

use php\manager\crontab\CrontabManager;

$crontab = new CrontabManager();
$crontab->enableOrUpdate('/tmp/my/crontab.txt');
$crontab->save();

Zarządzanie poszczególnymi zadaniami z API:

use php\manager\crontab\CrontabManager;

$crontab = new CrontabManager();
$job = $crontab->newJob();
$job->on('* * * * *');
$job->onMinute('20-30')->doJob("echo foo");
$crontab->add($job);
$job->onMinute('35-40')->doJob("echo bar");
$crontab->add($job);
$crontab->save();

github: php-crontab-manager

Chris Suszyński
źródło
Miły. To na pewno się przyda ... zakładając, że faktycznie zadziała :)
Baraka
@Pacerier ten projekt wydaje się martwy i ma pewne problemy. Spróbuj yzalis / crontab, który jest bardziej aktywny.
Jeff Puckett
10

Sprawdź cronjob

function cronjob_exists($command){

    $cronjob_exists=false;

    exec('crontab -l', $crontab);


    if(isset($crontab)&&is_array($crontab)){

        $crontab = array_flip($crontab);

        if(isset($crontab[$command])){

            $cronjob_exists=true;

        }

    }
    return $cronjob_exists;
}

Dołącz cronjob

function append_cronjob($command){

    if(is_string($command)&&!empty($command)&&cronjob_exists($command)===FALSE){

        //add job to crontab
        exec('echo -e "`crontab -l`\n'.$command.'" | crontab -', $output);


    }

    return $output;
}

Usuń plik crontab

exec('crontab -r', $crontab);

Przykład

exec('crontab -r', $crontab);

append_cronjob('* * * * * curl -s http://localhost/cron/test1.php');

append_cronjob('* * * * * curl -s http://localhost/cron/test2.php');

append_cronjob('* * * * * curl -s http://localhost/cron/test3.php');
RafaSashi
źródło
funkcja append_cronjob nie działa dla mnie. Otrzymuję wynik „-” nie istnieje: Array ([0] => „-” nie istnieje. [1] => użycie: plik crontab [2] => crontab [-e | -l | -r] [3] => -e (edytuj crontab użytkownika) [4] => -l (wyświetl crontab użytkownika) [5] => -r (usuń crontab użytkownika))
user1307016
exec ('echo -e " crontab -l\ n'. $ polecenie. '" | crontab -', $ wyjście); czy to jest poprawne. Nie otrzymuję pliku crontab dla danych www "-": 0: złe błędy minutowe w pliku crontab, nie można zainstalować.
Rahul Tailwal
Crontab ogranicza zadania znakami końca wiersza (znaki nowej linii). Każda praca zajmuje jedną linię. Dlatego, jeśli crontab widzi coś innego niż liczbę całkowitą w pierwszej kolumnie wiersza, zgłasza błąd „zła minuta”, ponieważ argument minut jest pierwszym, który napotka crontab. sprawdź to dougv.com/2006/12/…
RafaSashi
dzięki ... jak mogę używać cron_TZ używając twojego projektu?
Salem Ahmed
5

To powinno wystarczyć

shell_exec("crontab -l | { cat; echo '*/1    *    *    *    *    command'; } |crontab -");
Fred
źródło
5

Wypróbowałem poniższe rozwiązanie

class Crontab {

// In this class, array instead of string would be the standard input / output format.

// Legacy way to add a job:
// $output = shell_exec('(crontab -l; echo "'.$job.'") | crontab -');

static private function stringToArray($jobs = '') {
    $array = explode("\r\n", trim($jobs)); // trim() gets rid of the last \r\n
    foreach ($array as $key => $item) {
        if ($item == '') {
            unset($array[$key]);
        }
    }
    return $array;
}

static private function arrayToString($jobs = array()) {
    $string = implode("\r\n", $jobs);
    return $string;
}

static public function getJobs() {
    $output = shell_exec('crontab -l');
    return self::stringToArray($output);
}

static public function saveJobs($jobs = array()) {
    $output = shell_exec('echo "'.self::arrayToString($jobs).'" | crontab -');
    return $output; 
}

static public function doesJobExist($job = '') {
    $jobs = self::getJobs();
    if (in_array($job, $jobs)) {
        return true;
    } else {
        return false;
    }
}

static public function addJob($job = '') {
    if (self::doesJobExist($job)) {
        return false;
    } else {
        $jobs = self::getJobs();
        $jobs[] = $job;
        return self::saveJobs($jobs);
    }
}

static public function removeJob($job = '') {
    if (self::doesJobExist($job)) {
        $jobs = self::getJobs();
        unset($jobs[array_search($job, $jobs)]);
        return self::saveJobs($jobs);
    } else {
        return false;
    }
}

}

kredyty dla: Crontab Class to Add, Edit and Remove Cron Jobs

Sam T
źródło
4

Możesz spróbować zastąpić EDITORzmienną środowiskową czymś w rodzaju, edktóry może przyjąć sekwencję poleceń edycji na standardowe wejście.

Alnitak
źródło
3

Zależy, gdzie przechowujesz swój plik crontab:

shell_exec('echo "'. $job .'" >> crontab');
dom
źródło
3

Możesz umieścić swój plik w /etc/cron.d/ w formacie cron. Dodaj unikalny prefiks do nazwy pliku Aby wyświetlić listę zadań cron specyficznych dla skryptu, po prostu pracuj z listą plików z unikalnym prefiksem. Usuń plik, jeśli chcesz wyłączyć zadanie.

Dmitry Kireev
źródło
Bardziej podoba mi się to rozwiązanie, ponieważ pozwala uniknąć manipulowania całym plikiem cron i jest łatwe do usunięcia, a nie konieczności dodawania i usuwania określonego zadania crona w ogromnym pliku cron.
Jovanni G
3

Fajnie ...
Spróbuj tego, aby usunąć określone zadanie crona (przetestowane).

<?php $output = shell_exec('crontab -l'); ?>
<?php $cron_file = "/tmp/crontab.txt"; ?>

<!-- Execute script when form is submitted -->
<?php if(isset($_POST['add_cron'])) { ?>

<!-- Add new cron job -->
<?php if(!empty($_POST['add_cron'])) { ?>
<?php file_put_contents($cron_file, $output.$_POST['add_cron'].PHP_EOL); ?>
<?php } ?>

<!-- Remove cron job -->
<?php if(!empty($_POST['remove_cron'])) { ?>
<?php $remove_cron = str_replace($_POST['remove_cron']."\n", "", $output); ?>
<?php file_put_contents($cron_file, $remove_cron.PHP_EOL); ?>
<?php } ?>

<!-- Remove all cron jobs -->
<?php if(isset($_POST['remove_all_cron'])) { ?>
<?php echo exec("crontab -r"); ?>
<?php } else { ?>
<?php echo exec("crontab $cron_file"); ?>
<?php } ?>

<!-- Reload page to get updated cron jobs -->
<?php $uri = $_SERVER['REQUEST_URI']; ?>
<?php header("Location: $uri"); ?>
<?php exit; ?>
<?php } ?>

<b>Current Cron Jobs:</b><br>
<?php echo nl2br($output); ?>

<h2>Add or Remove Cron Job</h2>
<form method="post" action="<?php $_SERVER['REQUEST_URI']; ?>">
<b>Add New Cron Job:</b><br>
<input type="text" name="add_cron" size="100" placeholder="e.g.: * * * * * /usr/local/bin/php -q /home/username/public_html/my_cron.php"><br>
<b>Remove Cron Job:</b><br>
<input type="text" name="remove_cron" size="100" placeholder="e.g.: * * * * * /usr/local/bin/php -q /home/username/public_html/my_cron.php"><br>
<input type="checkbox" name="remove_all_cron" value="1"> Remove all cron jobs?<br>
<input type="submit"><br>
</form>
Ajie Kurniyawan
źródło
Pamiętaj, aby dodać exit;po header('Location: ...');. Ta forma jest również dość niebezpieczna, ponieważ może dodać zadanie crona do „zniszczenia” serwera.
Raptor,
1
Uwaga dla początkujących: tak naprawdę nie zawijamy każdej linii PHP w znaczniki PHP. Wystarczy jeden na początku PHP i opcjonalnie jeden na końcu.
ekerner
0

Najłatwiejszym sposobem jest użycie polecenia shell_exec do wykonania skryptu bash, przekazując wartości jako parametry. Stamtąd możesz manipulować crontabami, tak jak w każdym innym nieinteraktywnym skrypcie, a także upewnić się, że masz odpowiednie uprawnienia, używając sudo itp.

Zobacz to, Crontab bez crontab -e , aby uzyskać więcej informacji.

Codemwnci
źródło
Niektóre osoby mogą znajdować się na wspólnym hoście, więc może to w ogóle nie działać.
TheRealChx101
-1

Zamiast crontab można również użyć kolejki zadań silnika aplikacji Google . Ma hojny darmowy przydział, jest szybki, skalowalny, modyfikowalny.

Alfred
źródło
3
Dlaczego po prostu nie użyć cronjob?
Pacerier,
-1

To proste Możesz to zrobić curl, upewnij się, że curl jest zainstalowany na serwerze:

do wyzwalania co minutę: * * * * * curl --request POST ' https://glassdoor.com/admin/sendBdayNotification '

        • *

    minuta godzina dzień miesiąc tydzień

Powiedzmy, że chcesz wysyłać to powiadomienie codziennie o 14:15 Możesz zmienić POST / GET na podstawie swojego API:

15 14 * * * curl --request POST 'url url API'

dinesh kandpal
źródło