--
KritsanaMunwong - 06 Feb 2007
crontab บน Linux
================
คำสั่ง crontab เป็นคำสั่งในการทำ schedule ในการสั่งโปรแกรม หรือ script ต่างๆ ทำงานตามเวลาที่กำหนด บนระบบ UNIX/LINUX
ซึ่งอำนวยความสะดวกได้มากเลยที่เดียว งานบางอย่างที่จำเป็นต้องทำซ้ำๆในเวลาเดียวกัน ไม่ว่าจะทุกวัน ทุกสัปดาห์ หรือ ทุกเดือน
การใช้งาน crontab
คำสั่งและ option ของ crontab มีดังนี้
Code:
crontab filename การนำเอาคำสั่ง crontab เข้ามาจาก ไฟล์อื่น
crontab -e แก้ไข crontab ปัจจุบัน
crontab -l ดูคำสั่ง crontab ทั้งหมดที่มีอยู่
crontab -r ลบคำสั่ง crontab ที่มีทั้งหมด
crontab -u user เป็นคำสั่งของผู้ดูแลระบบเท่านั้น(administrators) เพื่อใช้ดู แก้ไข ลบ crontab ของ user แต่ล่ะคน
เมื่อเรียกคำสั่งตามข้างบนแล้ว crontab จะเข้าสู่ระบบการ กำหนด หรือ แก้ไข ซึ่งการ กำหนด หรือแก้ไขนี้ จะเหมือนกับการใช้งาน vi ครับ
ถ้าใครเคยใช้งาน vi แล้วก็จะไม่มีปัญหาอะไร ถ้าไม่เคยใช้ ก็ดูคำสั่งพื้นฐานของ vi ด้านล่างนะครับ
เมื่อเรียกโปรแกรม crontab ให้ทำงานและขณะอยู่ในโปรแกรม เราสามารถกดคีย์ ดังต่อไปนี้เพื่อ
Code:
Esc เพื่อออกมาสู่โหมดปกติ
i เพื่อการเพิ่ม คำสั่ง ข้อความ เข้าไปใหม่
x ลบ ตัวอักษรที่ cursor วางอยู่ ทีละอักษร ในโหมดปกติ
dd ลบบรรทัด ทั้งบรรทัด ที่ cursor วางอยู่ทีละแถว ในโหมดปกติ
:q! ออกโดยไม่ต้องแก้ไขอะไร
:wq! เก็บบันทึกข้อความที่แก้ไขแล้วออกจากโปรแกรม
คำสั่งเหล่านี้เป็นแค่บางส่วนเท่านั้น แต่ก็พอใช้งานคำสั่ง crontab แล้วล่ะครับ ถ้าใครอยากได้มากกว่านี้ต้องศึกษาเพิ่มเอาอีกที
การกำหนดให้ crontab ทำงาน
format ของคำสั่ง crontab มีทั้งหมด 6 fields เป็นดังบรรทัดข้างล่าง
Code:
minute(s) hour(s) day(s) month(s) weekday(s) command(s)
fields 1-5 เป็นการกำหนดเวลา และ field ที่ 6 เป็นการกำหนดคำสั่ง ดังความหมายของแต่ละ fields ดังต่อไปนี้
Code:
........................................................................................................................................
Field มีค่า รายละเอียด
........................................................................................................................................
minute 0-59 เวลาเป็นนาที จะสั่งให้คำสั่งที่กำหนดทำงานทันทีเมื่อถึง
hour 0-23 เวลาเป็นชั่วโมง จะสั่งให้คำสั่งที่กำหนดทำงานทันทีเมื่อถึง
day 1-31 เวลาเป็นวัน จะสั่งให้คำสั่งที่กำหนดทำงานทันทีเมื่อถึง
month 1-12 เวลาเป็นเดือน จะสั่งให้คำสั่งที่กำหนดทำงานทันทีเมื่อถึง
weekday 0-6 วันของแต่ละสัปดาห์ มีค่าดังนี้ (อาทิตย์ = 0, จันทร์ = 1, อังคาร = 2, พุธ = 3,
พฤหัส = 4, ศุกร์ = 5 และ เสาร์ = 6)
command คำสั่ง เราสามารถกำหนดคำสั่งได้มากมาย รวมทั้ง script ต่างๆ ตามที่เราต้องการ
ตัวอย่างการกำหนด crontab
Fields
# Use the hash sign to prefix a comment
# +---------------- minute (0 - 59)
# | +------------- hour (0 - 23)
# | | +---------- day of month (1 - 31)
# | | | +------- month (1 - 12)
# | | | | +---- day of week (0 - 7) (Sunday=0 or 7)
# | | | | |
# * * * * * command to be executed
Crontab file for adm user on AIX system
#=================================================================
# SYSTEM ACTIVITY REPORTS
# 8am-5pm activity reports every 20 mins during weekdays.
# activity reports every hour on Saturday and Sunday.
# 6pm-7am activity reports every hour during weekdays.
# summary prepared at 18:05 every weekday.
#=================================================================
0,20,40 8-17 * * 1-5 /usr/lib/sa/sa1 1200 3 &
0 * * * 0,6 /usr/lib/sa/sa1 &
0 18-7 * * 1-5 /usr/lib/sa/sa1 &
5 18 * * 1-5 /usr/lib/sa/sa2 -s 8:00 -e 18:01 -i 3600 -ubcwyaqvm &
การเพิ่ม crontab โดยเรียกใช้คำสั่ง crontab -e เมื่อเข้าสู่โปรแกรมแล้ว กด i เพื่อเพิ่ม คำสั่งดังตัวอย่างด้านล่างนี้เข้าไป แล้วทำการบันทึก
แล้วออกมาโดยกด Esc แล้วกด :wq!
Code:
0 8 * * * /usr/bin/mplayer /home/tuxzilla/music/คุณครูครับ.mp3
จากคำสั่งด้านบนจะเป็นการสั่งให้โปรแกรม mplayer เล่นเพลง คุณครูครับ.mp3 ตอน 08:00 น. ของทุกๆวัน (เวลาตื่นนอนของผมเอง)
Code:
0 0 * * 1 /home/tuxzilla/getlogs.pl
จากคำสั่งด้านบน จะทำการ Run script getlogs.pl ที่ path /home/tuxzilla ทุกวันจันทร์ ทุกๆเดือน ตอนเที่ยงคืน
Code:
0 0 * * 1,5 /home/tuxzilla/getlogs.pl
คำสั่งนี้เหมือนคำสั่งด้านบนครับ แต่จะเพิ่มการทำงานในวันศุกร์ด้วย ซึ่งเราสามารถใช้ "," คั่นไปเรื่อยๆได้ เพื่อที่จะกำหนดเพิ่มให้แต่ล่ะ fields หรือใช้ "*"
เพื่อการกำหนดเป็นทั้งหมด(หมายความว่า หากที่ field ชั่วโมง เป็น * ก็หมายความว่าต้องทำงานทุกชั่วโมง)
ถึงจะมีหลาย user ในเครื่องเดียวกันแต่ยังไง crontab ก้ยังเป็นของใครของมันไม่กวนกันครับ และไม่สามารถดูของกันและกันได้ นอกจากเป็น
ผู้ดูแลระบบครับ ถึงตรงนี้แล้วก็คงไม่มีอะไรยากเกินกว่าแล้ว หากแต่ความสะดวกเท่านั้นที่จะมาแทนที หรือใครจะเอามาเป็นนาฬิกา อย่างผมก็ไม่ว่าครับ
คำสั่งเพิ่มเติมที่ควรรู้
man crontab
man cron
man at
man batch[/u]
ตัวอย่างการใช้งาน crontab
if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );
// Check minimum permission:
$current_User->check_perm( 'options', 'view', true );
$AdminUI->set_path( 'tools', 'cron' );
param( 'action', 'string', 'list' );
// We want to remember these params from page to page:
param( 'ctst_pending', 'integer', 0, true );
param( 'ctst_started', 'integer', 0, true );
param( 'ctst_timeout', 'integer', 0, true );
param( 'ctst_error', 'integer', 0, true );
param( 'ctst_finished', 'integer', 0, true );
param( 'results_crontab_order', 'string', '-A', true );
param( 'results_crontab_page', 'integer', 1, true );
// fp> The if below was the point where THE LINE WAS CROSSED!
// This is bloated here. This has to go into the action handling block (and maybe a function)
// THIS IS NO LONGER CONTROLLER INITIALIZATION. THIS IS ACTION EXECUTION!
// dh> ok. Moved the other param inits above. Ok? I don't think it should be an extra function..
// Init names and params for "static" available jobs and ask Plugins about their jobs:
if( $action == 'new' || $action == 'create' )
{
// NOTE: keys starting with "plugin_" are reserved for jobs provided by Plugins
$cron_job_names = array(
'test' => T_('Basic test job'),
'error' => T_('Error test job'),
'anstispam_poll' => T_('Poll the antispam blacklist'),
'prune_hits_sessions' => T_('Prune old hits & sessions'),
// post notifications, not user schedulable
);
$cron_job_params = array(
'test' => array(
'ctrl' => 'cron/_test.job.php',
'params' => NULL ),
'error' => array(
'ctrl' => 'cron/_error_test.job.php',
'params' => NULL ),
'anstispam_poll' => array(
'ctrl' => 'cron/_antispam_poll.job.php',
'params' => NULL ),
'prune_hits_sessions' => array(
'ctrl' => 'cron/_prune_hits_sessions.job.php',
'params' => NULL ),
// post notifications, not user schedulable
);
// Get additional jobs from Plugins:
foreach( $Plugins->trigger_collect( 'GetCronJobs' ) as $plug_ID => $jobs )
{
if( ! is_array($jobs) )
{
$Debuglog->add( sprintf('GetCronJobs() for plugin #%d did not return array. Ignoring its jobs.', $plug_ID), array('plugins', 'error') );
continue;
}
foreach( $jobs as $job )
{
// Validate params from plugin:
if( ! isset($job['params']) )
{
$job['params'] = NULL;
}
if( ! is_array($job) || ! isset($job['ctrl'], $job['name']) )
{
$Debuglog->add( sprintf('GetCronJobs() for plugin #%d did return invalid job. Ignoring.', $plug_ID), array('plugins', 'error') );
continue;
}
if( isset($job['params']) && ! is_array($job['params']) )
{
$Debuglog->add( sprintf('GetCronJobs() for plugin #%d did return invalid job params (not an array). Ignoring.', $plug_ID), array('plugins', 'error') );
continue;
}
$ctrl_id = 'plugin_'.$plug_ID.'_'.$job['ctrl'];
$cron_job_names[$ctrl_id] = $job['name'];
$cron_job_params[$ctrl_id] = array(
'ctrl' => $ctrl_id,
'params' => $job['params'],
);
}
}
}
switch( $action )
{
case 'new':
// Check that we have permission to edit options:
$current_User->check_perm( 'options', 'edit', true, NULL );
break;
case 'create':
// Check that we have permission to edit options:
$current_User->check_perm( 'options', 'edit', true, NULL );
// CREATE OBJECT:
load_class( '/MODEL/cron/_cronjob.class.php' );
$edited_Cronjob = & new Cronjob();
$cjob_type = param( 'cjob_type', 'string', true );
if( !isset( $cron_job_params[$cjob_type] ) )
{
param_error( 'cjob_type', T_('Invalid job type') );
}
// start datetime:
param_date( 'cjob_date', T_('Please enter a valid date.'), true );
param_time( 'cjob_time' );
$edited_Cronjob->set( 'start_datetime', form_date( get_param( 'cjob_date' ), get_param( 'cjob_time' ) ) );
// repeat after:
$cjob_repeat_after_days = param( 'cjob_repeat_after_days', 'integer', 0 );
$cjob_repeat_after_hours = param( 'cjob_repeat_after_hours', 'integer', 0 );
$cjob_repeat_after_minutes = param( 'cjob_repeat_after_minutes', 'integer', 0 );
$cjob_repeat_after = ( ( ($cjob_repeat_after_days*24) + $cjob_repeat_after_hours )*60 + $cjob_repeat_after_minutes)*60; // seconds
if( $cjob_repeat_after == 0 )
{
$cjob_repeat_after = NULL;
}
$edited_Cronjob->set( 'repeat_after', $cjob_repeat_after );
// name:
$edited_Cronjob->set( 'name', $cron_job_names[$cjob_type] );
// controller:
$edited_Cronjob->set( 'controller', $cron_job_params[$cjob_type]['ctrl'] );
// params:
$edited_Cronjob->set( 'params', $cron_job_params[$cjob_type]['params'] );
if( ! param_errors_detected() )
{ // No errors
// Save to DB:
$edited_Cronjob->dbinsert();
$Messages->add( T_('New job has been scheduled.'), 'success' );
$action = 'list';
}
break;
case 'delete':
// Make sure we got an ord_ID:
param( 'ctsk_ID', 'integer', true );
// Check that we have permission to edit options:
$current_User->check_perm( 'options', 'edit', true, NULL );
// TODO: prevent deletion of running tasks.
$DB->begin();
$tsk_status = $DB->get_var(
'SELECT clog_status
FROM T_cron__log
WHERE clog_ctsk_ID= '.$ctsk_ID,
0, 0, 'Check that task is not running' );
if( $tsk_status == 'started' )
{
$DB->rollback();
$Messages->add( sprintf( T_('Job #%d is currently running. It cannot be deleted.'), $ctsk_ID ), 'error' );
}
else
{
// Delete task:
$DB->query( 'DELETE FROM T_cron__task
WHERE ctsk_ID = '.$ctsk_ID );
// Delete log (if exists):
$DB->query( 'DELETE FROM T_cron__log
WHERE clog_ctsk_ID = '.$ctsk_ID );
$DB->commit();
$Messages->add( sprintf( T_('Scheduled job #%d deleted.'), $ctsk_ID ), 'success' );
}
forget_param( 'ctsk_ID' );
$action = 'list';
break;
case 'view':
$cjob_ID = param( 'cjob_ID', 'integer', true );
$sql = 'SELECT *
FROM T_cron__task LEFT JOIN T_cron__log ON ctsk_ID = clog_ctsk_ID
WHERE ctsk_ID = '.$cjob_ID;
$cjob_row = $DB->get_row( $sql, OBJECT, 0, 'Get cron job and log' );
if( empty( $cjob_row ) )
{
$Messages->add( sprintf( T_('Job #%d does not exist any longer.'), $cjob_ID ), 'error' );
$action = 'list';
}
break;
case 'list':
// Detect timed out tasks:
$sql = ' UPDATE T_cron__log
SET clog_status = "timeout"
WHERE clog_status = "started"
AND clog_realstart_datetime < '.$DB->quote( date2mysql( time() + $time_difference - $cron_timeout_delay ) );
$DB->query( $sql, 'Detect cron timeouts.' );
break;
}
// Display ... section! (Note: should be done early if actions do not redirect)
$AdminUI->disp_html_head();
// Display title, menu, messages, etc. (Note: messages MUST be displayed AFTER the actions)
$AdminUI->disp_body_top();
// Begin payload block:
$AdminUI->disp_payload_begin();
switch( $action )
{
case 'new':
case 'create':
// Display VIEW:
$AdminUI->disp_view( 'cron/_cronjob.form.php' );
break;
case 'view':
// Display VIEW:
$AdminUI->disp_view( 'cron/_cronjob.sheet.php' ); // uses $cjob_row
break;
default:
// Display VIEW:
$AdminUI->disp_view( 'cron/_crontab.list.php' );
}
// End payload block:
$AdminUI->disp_payload_end();
// Display body bottom, debug info and close :
$AdminUI->disp_global_footer();
?>