ใช้ PHP เพื่อสร้างแก้ไขและลบงาน crontab?


116

เป็นไปได้หรือไม่ที่จะใช้ PHP เพื่อสร้างแก้ไขและลบงาน crontab

ฉันรู้วิธีแสดงรายการงาน crontab ปัจจุบันของผู้ใช้ Apache:

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

แต่จะเพิ่มงาน cron ด้วย PHP ได้อย่างไร? 'crontab -e' จะเปิดโปรแกรมแก้ไขข้อความและคุณจะต้องแก้ไขรายการด้วยตนเองก่อนบันทึกไฟล์

แล้วจะลบ cron job ด้วย PHP ได้อย่างไร? คุณต้องทำสิ่งนี้ด้วยตนเองอีกครั้งโดย 'crontab -e'

ด้วยสตริงงานดังนี้:

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

ฉันจะเพิ่มลงในรายการงาน crontab ด้วย PHP ได้อย่างไร


2
เป็นไปได้ที่จะทำซ้ำงาน Cron โดยใช้ phpและอีกสองสามงาน
Gordon

14
(คำใบ้) crontab เป็นเพียงไฟล์
Gordon

1
@ กอร์ดอนขอบคุณ ฉันรู้ว่าทุกอย่างเป็นไฟล์ แต่พวกเขาจัดเก็บงาน crontab ในเส้นทางเดียวกันใน distros ที่แตกต่างกันหรือไม่ นอกจากนี้จะต้องได้รับผู้ใช้ Apache เช่น www-data และมีสิทธิ์ของ root?
datasn.io

ฉันไม่แน่ใจว่าเส้นทางจะเปลี่ยนไปตาม distros หรือไม่ แต่คุณทำได้ดีที่จะทำให้เส้นทางมีค่าที่กำหนดได้ในโค้ดของคุณและตั้งค่าในรันไทม์ สำหรับผู้ใช้และสิทธิ์: ผู้ใช้ทุกคนสามารถมี crontab ที่รันงานด้วยสิทธิ์ที่กำหนดให้กับผู้ใช้รายนั้นดังนั้นจึงเป็นรายบุคคลสำหรับการตั้งค่าระบบของคุณ
Gordon

คำตอบ:


133

การใช้คำสั่ง 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)

ดังนั้น,

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

ข้างต้นสามารถใช้ได้ทั้งสร้างและแก้ไข / ผนวกหากผู้ใช้มีสิทธิ์ในการเขียนไฟล์ที่เพียงพอ

ในการลบงาน:

echo exec('crontab -r');

นอกจากนี้โปรดทราบว่า apache กำลังทำงานในฐานะผู้ใช้เฉพาะและโดยปกติจะไม่ใช่รูทซึ่งหมายความว่างาน cron สามารถเปลี่ยนแปลงได้สำหรับผู้ใช้ apache เท่านั้นเว้นแต่จะให้crontab -uสิทธิ์แก่ผู้ใช้ apache


4
'crontab -r' จะไม่ลบงานทั้งหมดของผู้ใช้หรือไม่? มีวิธีใดในการลบสายงานเฉพาะใน crontabs ของผู้ใช้หรือไม่? การโหลดค้นหาและลบบรรทัดที่พบดูเหมือนจะเป็นวิธีเดียว
datasn.io

3
คุณสามารถใช้ไปป์แทนการเขียนไฟล์ชั่วคราวได้
realmfoo

7
ทางออกที่ดี แต่shell_exec('crontab -l')จะส่งคืนเฉพาะบรรทัดสุดท้าย ฉันใช้exec('crontab -l', $output). จากนั้นใส่อาร์เรย์เอาต์พุต $ เป็นสตริง (โดยมี \ n เป็นกาว)
David Fairbanks

1
@Rahul ถ้าผู้ให้บริการเซิร์ฟเวอร์ไม่ได้ให้คำสั่งเปลือกเช่นsystem(), passthru(), shell_exec()และexec()ลองใช้แผงควบคุมที่มาพร้อมกับโฮสติ้งเช่น cPanel หรือ Plesk
Raptor

3
ซึ่งจะต่อท้ายงานเดียวกันทุกครั้งในไฟล์ (ทำเครื่องหมาย) มีวิธีลบงานที่ตรงกันก่อนแล้วจึงเขียนงานใหม่หรือไม่?
RT

20

เมื่อเร็ว ๆ นี้เราได้เตรียมโครงการขนาดเล็ก (PHP> = 5.3) เพื่อจัดการไฟล์ cron สำหรับงานส่วนตัวและงานแต่ละงาน เครื่องมือนี้เชื่อมต่อและจัดการไฟล์ cron เพื่อให้คุณสามารถใช้งานได้เช่นต่อโปรเจ็กต์ มีการทดสอบหน่วย :-)

ตัวอย่างจากบรรทัดคำสั่ง:

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

ตัวอย่างจาก API:

use php\manager\crontab\CrontabManager;

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

การจัดการงานแต่ละงานจาก 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


ดี สิ่งนี้จะมีประโยชน์อย่างแน่นอน ... สมมติว่าใช้งานได้จริง :)
Baraka

@Pacerier โครงการนี้ดูเหมือนจะตายไปแล้วและมีปัญหาบางอย่าง ลองyzalis / crontabซึ่งใช้งานได้มากกว่า
Jeff Puckett

10

ตรวจสอบ 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;
}

ต่อท้าย 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;
}

ลบ crontab

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

ตัวอย่าง

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');

ฟังก์ชัน append_cronjob ไม่ทำงานสำหรับฉัน ฉันได้รับผลลัพธ์ '-' ไม่มีอยู่: ไม่มี Array ([0] => '-' [1] => การใช้งาน: ไฟล์ crontab [2] => crontab [-e | -l | -r] [3] => -e (แก้ไข crontab ของผู้ใช้) [4] => -l (crontab ของผู้ใช้รายชื่อ) [5] => -r (ลบ crontab ของผู้ใช้))
user1307016

exec ('echo -e " crontab -l\ n'. $ command. '" | crontab -', $ output); ถูกต้องหรือไม่ ฉันไม่ได้รับ crontab สำหรับ www-data "-": 0: ข้อผิดพลาด bad minute ในไฟล์ crontab ไม่สามารถติดตั้งได้
Rahul Tailwal

Crontab คั่นระหว่างงานด้วยการขึ้นบรรทัดใหม่ แต่ละงานมีหนึ่งบรรทัด ดังนั้นหาก crontab เห็นสิ่งอื่นนอกเหนือจากจำนวนเต็มในคอลัมน์แรกของบรรทัดมันจะแสดงข้อผิดพลาด "นาทีที่ไม่ดี" เนื่องจากอาร์กิวเมนต์ลิปดาเป็นอาร์กิวเมนต์แรกที่พบใน crontab ลองดูที่dougv.com/2006/12/…
RafaSashi

ขอบคุณ ... ฉันจะใช้ cron_TZ กับโครงการของคุณได้อย่างไร ??
Salem Ahmed


5

ฉันลองวิธีแก้ปัญหาด้านล่างแล้ว

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;
    }
}

}

ให้เครดิตกับ: Crontab Class เพื่อเพิ่มแก้ไขและลบงาน Cron


4

คุณสามารถลองแทนที่EDITORตัวแปรสภาพแวดล้อมด้วยสิ่งที่ต้องการedซึ่งสามารถใช้ลำดับของคำสั่งแก้ไขมากกว่าอินพุตมาตรฐาน


3

ขึ้นอยู่กับตำแหน่งที่คุณจัดเก็บ crontab ของคุณ:

shell_exec('echo "'. $job .'" >> crontab');

3

คุณสามารถใส่ไฟล์ของคุณเป็น /etc/cron.d/ ในรูปแบบ cron เพิ่มคำนำหน้าที่ไม่ซ้ำกันให้กับ filenaname หากต้องการแสดงรายการงาน cron เฉพาะสคริปต์เพียงแค่ทำงานกับรายการไฟล์ที่มีคำนำหน้าเฉพาะ ลบไฟล์เมื่อคุณต้องการปิดงาน


ฉันชอบโซลูชันนี้ดีกว่าเพราะหลีกเลี่ยงการจัดการไฟล์ cron ทั้งหมดและง่ายต่อการลบเมื่อเทียบกับการต้องเพิ่มและลบงาน cron เฉพาะในไฟล์ cron ขนาดใหญ่
Jovanni G

3

ดี ...
ลองทำเช่นนี้เพื่อลบงาน cron เฉพาะ (ทดสอบแล้ว)

<?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>

อย่าลืมเพิ่มหลังexit; header('Location: ...');นอกจากนี้แบบฟอร์มนี้ค่อนข้างอันตรายเนื่องจากสามารถเพิ่มงาน cron เพื่อ "ทำลาย" เซิร์ฟเวอร์ได้
Raptor

1
หมายเหตุสำหรับผู้เริ่มต้น: เราไม่ได้รวม PHP ทุกบรรทัดในแท็ก PHP หนึ่งที่จุดเริ่มต้นของ PHP และอีกทางเลือกหนึ่งในตอนท้ายก็เพียงพอแล้ว
ekerner

0

วิธีที่ง่ายที่สุดคือใช้คำสั่ง shell_exec เพื่อรันสคริปต์ bash โดยส่งผ่านค่าเป็นพารามิเตอร์ จากนั้นคุณสามารถจัดการ crontabs ได้เช่นเดียวกับที่คุณทำในสคริปต์อื่น ๆ ที่ไม่ใช่แบบโต้ตอบและตรวจสอบให้แน่ใจว่าคุณมีสิทธิ์ที่ถูกต้องโดยใช้ sudo เป็นต้น

ดูสิ่งนี้Crontab ที่ไม่มี crontab -eสำหรับข้อมูลเพิ่มเติม


บางคนอาจอยู่ในโฮสต์ที่ใช้ร่วมกันดังนั้นสิ่งนี้อาจไม่ได้ผลเลย
TheRealChx101

-1

แทนที่จะใช้ crontab คุณสามารถใช้คิวงานแอปเอ็นจิ้นของ Google ได้ มีโควต้าฟรีมากมายรวดเร็วปรับขนาดปรับเปลี่ยนได้


3
ทำไมไม่ใช้ cronjob?
Pacerier

-1

มันง่ายมากคุณสามารถทำ curl ได้ตรวจสอบให้แน่ใจว่า curl ติดตั้งบนเซิร์ฟเวอร์:

สำหรับการทริกเกอร์ทุกนาที: * * * * * curl --request POST ' https://glassdoor.com/admin/sendBdayNotification '

        • * * * *

    นาทีชั่วโมงวันเดือนสัปดาห์

สมมติว่าคุณต้องการส่งการแจ้งเตือนนี้ 14:15 น. ทุกวัน คุณสามารถเปลี่ยน POST / GET ตาม API ของคุณ:

15 14 * * * curl - ขอ POST 'url ของ ur API'

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.