ืืงืืืกืืงื ืืชืื ืฉืฉืขืืช ืฉืืืืช ืื ืฆืืคืื. ืืืื ืื ืืคืจืืขืื ืืื ืื ืืื ืืชืื ืชืื ืืื ืืื ืืงืก, ืืื ืืืื ืืชืื ืชืื ืืืืขืื ืืืืืืืช: cron ืืขืงืื ืืืจ ืืืื ืืืงืืื.
ืืื ืขืืจ ืฉื ืฉืืจืช ืืคืงืืื ืื ืื ืืืืฉื ืืื ืืืื ืขืืืจื. sed, awk, wc, cut ืืชืืื ืืืช ืืฉื ืืช ืืืจืืช ืืืคืขืืืช ืขื ืืื ืกืงืจืืคืืื ืืฉืจืชืื ืฉืื ื ืืื ืืื. ืจืืื ืืื ืืชืืื ื ืื ืืืฉืืืืช ืขืืืจ cron, ืืชืืื ืืืงืืจ ืืฉื ืืช ื-70.
ืืืฉื ืืื ืจื ืืฉืชืืฉืชื ื-cron ืืฆืืจื ืฉืืืืช, ืืืื ืืืืื ืก ืืคืจืืื, ืืื ืืื ืืื, ืืฉื ืชืงืืชื ืืฉืืืื ืืืคืขืืช ืกืงืจืืคื, ืืืืืชื ืืืืืง ืืช ืื ืืขืืืง. ืื ืืืคืืข ืืืืืจ ืืื, ืชืื ืืื ืืชืืืชื ืืืจืชื ืืช POSIX crontab, ืืคืฉืจืืืืช ืืงืจืื ืืขืืงืจืืืช ืืืคืฆืืช ืืื ืืงืก ืคืืคืืืจืืืช ืืืช ืืืื ื ืฉื ืืืงื.
ืืื ืืชื ืืฉืชืืฉ ืืืื ืืงืก ืืืคืขืื ืืฉืืืืช cron? ืืื ืืชื ืืชืขื ืืื ืืืจืืืืงืืืจืช ืืืฉืืื ืืขืจืืช ืืืื ืืงืก? ืื ืื ืื ื ืืืจื!
ืชืืื
ืืืฆื ืืืื ืื POSIX crontab ืื ืืืจ ืืืืชืจ - Vixie cron 3.0pl1 cron ืขื ืืืืื ืืืืืื ืื ืืงืืจื ื-Red Hat, Fedora ื- CentOS ืืงืืจื ื-SLES ืื-openSUSE ืืืฉืืจ Vixie cron ืืืจืืช ืืืจ
ืืืฆื ืืืื ืื
ืืคืขืื ืชืงืืคืชืืช ืฉื ืชืืื ืืืช ืืฉืชืืฉ ืื ืืขืจืืช ืืื ืืืจื ืืจืืจ ืืื ืืขืจืืืช ืืืคืขืื. ืืื, ืืชืื ืชืื ืืืื ื ืืช ืืฆืืจื ืืฉืืจืืชืื ืืืืคืฉืจืื ืืื ืืชืื ื ืืืืฆืข ืืฉืืืืช ืืืืคื ืืจืืื ืืคื ื ืืื ืจื.
ืืขืจืืืช ืืคืขืื ืืืืืืช Unix ืขืืงืืืช ืืืจ ืืงืืจืืชืืื ืืืจืกื 7 Unix, ืฉืคืืชืื ืืฉื ืืช ื-70 ืฉื ืืืื ืืงืืืืช ื-Bell Labs, ืืืื ืขื ืืื ืงื ืชืืืคืกืื ืืืคืืจืกื. ืืจืกื 7 Unix ืืืื ืื cron, ืฉืืจืืช ืืืคืขืืช ืืฉืืืืช ืืฉืชืืฉ-ืขื ืืืืคื ืงืืืข.
ืงืจืื ืืืืจื ื ืืืคืืกื ืืื ืชืืื ื ืคืฉืืื, ืืื ืืืืืจืืชื ืืืคืขืื ืฉื ืืืจืกื ืืืงืืจืืช ืืื ืืคืืื ืคืฉืื ืืืชืจ: ืืฉืืจืืช ืืชืขืืจืจ ืคืขื ืืืงื, ืงืจื ืืืื ืขื ืืฉืืืืช ืืงืืืฅ ืืืื (/etc/lib/crontab) ืืืืฆืข ืขืืืจ ืืฉืชืืฉ-ืขื ืืช ืืืฉืืืืช ืฉืืื ืืืืจืืช ืืืชืืฆืข ืืจืืข ืื ืืืื.
ืืืืจ ืืื, ืืจืกืืืช ืืฉืืคืจืืช ืฉื ืืฉืืจืืช ืืคืฉืื ืืืฉืืืืฉื ืกืืคืงื ืขื ืื ืืขืจืืืช ืืืคืขืื ืืืืืืช ืืื ืืงืก.
ืชืืืืจืื ืืืืืื ืฉื ืคืืจืื crontab ืืืขืงืจืื ืืช ืืืกืืกืืื ืฉื ืคืขืืืช ืืื ืืฉืืจืืช ื ืืืื ืืชืงื ืืจืืฉื ืฉื ืืขืจืืืช ืืคืขืื ืืืืืืช Unix - POSIX - ืืฉื ืช 1992, ืืื ืืคื cron ืืชืงื ืื ืคืงืื ืืชืงื ืื ืืืจื.
ืืฉื ืช 1987, ืคืื Vixie, ืืืืจ ืฉืกืงืจ ืืช ืืฉืชืืฉื ืืื ืืงืก ืืืื ืจืฆืื ืืชืืื ืขืืืจ cron, ืืืฆืื ืืจืกื ื ืืกืคืช ืฉื ืืืืื ืฉืชืืงื ื ืืืง ืืืืขืืืช ืฉื cron ืืืกืืจืชื ืืืจืืืื ืืช ืืชืืืืจ ืฉื ืงืืฆื ืืืื.
ืืืจืกื ืืฉืืืฉืืช ืฉื Vixie cron ืืืื ืืขืืื ืืืจืืฉืืช POSIX, ืื ืืกืฃ, ืืชืืื ืืช ืืื ืจืืฉืืื ืืืืจืื, ืื ืืืชืจ ืืืืง ืื ืืื ืจืืฉืืื ืืื, ืืืขื ืืืฉืืืืช ื-README: ืืืืืจ ืืื ื ื ืืชื ืขืจืืืืืช, ืฉื ืืืืืจ ืื ื ืืชื ืืืืืง, ืืืชืืื ืืช ืืืืื ืืืืืืจ ืจืง ืืื ืขื ืงืื ืืงืืจ. ืืืจืืฉืืช ืืืื ืืชืืจืจื ืืชืืืืืช ืืขืงืจืื ืืช ืืชืืื ื ืืืืคืฉืืช ืฉืฆืืจื ืคืืคืืืจืืืช ืืืืชื ืฉื ืื, ืื ืฉืืืง ืืืืคืฆืืช ืืืจืืืืืช ืฉื ืืื ืืงืก ืฉืืืคืืขื ืืชืืืืช ืฉื ืืช ื-90 ืืงืื ืืช Vixie cron ืืืขืจืืช ืืืช ืฉืืื ืืขืืืื ืืคืชืืืช ืืืชื ืืืื.
ืืืืืื, Red Hat ื-SUSE ืืคืชืืื ืืืื ืฉื Vixie cron - cron, ืืืืืื ืืืืืื ืื ืืฉืชืืฉืืช ืืืืืืจื ืืืงืืจืืช ืฉื Vixie cron ืขื ืชืืงืื ืื ืจืืื.
ืืืื ื ืืืจ ืชืืืื ืืช ื-User Utility crontab ืืืชืืืจ ื-POSIX, ืืืืืจ ืืื ื ืืื ืืช ืืจืืืืช ืืชืืืืจ ืื ืืชื ืืช ื-Vixie cron ืืืช ืืฉืืืืฉ ืืืืจืืืฆืืืช ืฉื Vixie cron ืืืคืฆืืช ืืื ืืงืก ืคืืคืืืจืืืช. ืืืืกืืฃ, ืืืืืืื ืฉืขื ืืขืืื ืืื ืื ืืชืื ืฉื ืืืฉืืจ ืืงืจืื ืืืื.
POSIX crontab
ืื ืืงืจืื ืืืงืืจื ืชืืื ืขืื ืขืืืจ ืืฉืชืืฉ ืืขื, ืืชืืื ืื ืืืืจื ืืื ืืชืืืืืื ืืขืชืื ืงืจืืืืช ืขื ืืฉืืืืช ืฉื ืืฉืชืืฉืื ืจืืืืื, ืืื ืืืื ืื ืื ืืืชืจ.
Crons ืืกืืคืงืื ืืกื ืฉื ืฉืชื ืชืืื ืืืช: ืืืื ื-cron ืืคืืขื ืืื ืืจืฃ ืืืื ืืฉืืจืืช crontab ืืืืื ื ืืืฉืชืืฉืื. ืืืืจืื ืืืคืฉืจ ืื ืืขืจืื ืืืืืืช ืืฉืืืืช ืกืคืฆืืคืืืช ืืื ืืฉืชืืฉ ืืืขืจืืช, ืืขืื ืืืืื ืืฉืืง ืืฉืืืืช ืืืืืืืช ืืฉืชืืฉ ืืืขืจืืช.
ะ
ืขื ืืื ืงืจืืื ืืืื ืืฉืืจืืช crontab, ืืชื ืืืื ืืขืฉืืช ืืจืืขื ืืืจืื: ืืขืจืื ืืช ืืืืช ืืืฉืืืืช ืฉื ืืืฉืชืืฉ ืืขืืจื, ืืืขืื ืืช ืืืืื ืืงืืืฅ, ืืืฆืื ืืช ืืืืช ืืืฉืืืืช ืื ืืืืืช ืืื ืงืืช ืืช ืืืืช ืืืฉืืืืช. ืืืืืืืช ืืืืคื ืืคืขืืื ืฉื ืืื ืืฉืืจืืช crontab:
crontab -e # ัะตะดะฐะบัะธัะพะฒะฐัั ัะฐะฑะปะธัั ะทะฐะดะฐั
crontab -l # ะฟะพะบะฐะทะฐัั ัะฐะฑะปะธัั ะทะฐะดะฐั
crontab -r # ัะดะฐะปะธัั ัะฐะฑะปะธัั ะทะฐะดะฐั
crontab path/to/file.crontab # ะทะฐะณััะทะธัั ัะฐะฑะปะธัั ะทะฐะดะฐั ะธะท ัะฐะนะปะฐ
ืืฉืืชืงืฉืจืื crontab -e
ืืืขืฉื ืฉืืืืฉ ืืขืืจื ืืืฆืืื ืืืฉืชื ื ืืกืืืื ืืกืื ืืจืื EDITOR
.
ืืืฉืืืืช ืขืฆืื ืืชืืืจืืช ืืคืืจืื ืืื:
# ัััะพะบะธ-ะบะพะผะผะตะฝัะฐัะธะธ ะธะณะฝะพัะธัััััั
#
# ะทะฐะดะฐัะฐ, ะฒัะฟะพะปะฝัะตะผะฐั ะตะถะตะผะธะฝััะฝะพ
* * * * * /path/to/exec -a -b -c
# ะทะฐะดะฐัะฐ, ะฒัะฟะพะปะฝัะตะผะฐั ะฝะฐ 10-ะน ะผะธะฝััะต ะบะฐะถะดะพะณะพ ัะฐัะฐ
10 * * * * /path/to/exec -a -b -c
# ะทะฐะดะฐัะฐ, ะฒัะฟะพะปะฝัะตะผะฐั ะฝะฐ 10-ะน ะผะธะฝััะต ะฒัะพัะพะณะพ ัะฐัะฐ ะบะฐะถะดะพะณะพ ะดะฝั ะธ ะธัะฟะพะปัะทัััะฐั ะฟะตัะตะฝะฐะฟัะฐะฒะปะตะฝะธะต ััะฐะฝะดะฐััะฝะพะณะพ ะฟะพัะพะบะฐ ะฒัะฒะพะดะฐ
10 2 * * * /path/to/exec -a -b -c > /tmp/cron-job-output.log
ืืืฉืช ืืฉืืืช ืืจืืฉืื ืื ืฉื ืืจืฉืืืืช: ืืงืืช [1..60], ืฉืขืืช [0..23], ืืื ืืืืืฉ [1..31], ืืืืฉืื [1..12], ืืื ืืฉืืืข [0. .6], ืืืฉืจ 0 ืืื ืืื ืจืืฉืื. ืืฉืื ืืืืจืื, ืืฉืืฉื, ืืื ืฉืืจื ืฉืชืชืืฆืข ืขื ืืื ืืชืืจืืื ืืคืงืืืืช ืืกืื ืืจืื.
ืืืืฉืช ืืฉืืืช ืืจืืฉืื ืื, ื ืืชื ืืจืฉืื ืขืจืืื ืืืคืจืืื ืืคืกืืงืื:
# ะทะฐะดะฐัะฐ, ะฒัะฟะพะปะฝัะตะผะฐั ะฒ ะฟะตัะฒัั ะธ ะดะตััััั ะผะธะฝััั ะบะฐะถะดะพะณะพ ัะฐัะฐ
1,10 * * * * /path/to/exec -a -b -c
ืื ืขื ืืงืฃ:
# ะทะฐะดะฐัะฐ, ะฒัะฟะพะปะฝัะตะผะฐั ะฒ ะบะฐะถะดัั ะธะท ะฟะตัะฒัั
ะดะตัััะธ ะผะธะฝัั ะบะฐะถะดะพะณะพ ัะฐัะฐ
0-9 * * * * /path/to/exec -a -b -c
ืืืฉืช ืืืฉืชืืฉ ืืชืืืื ืืืฉืืืืช ืืืกืืจืช ื-POSIX ืขื ืืื ืืงืืฆืื cron.allow ื-cron.deny, ืืืคืจืืื ืืฉืชืืฉืื ืขื ืืืฉื ื-crontab ืืืฉืชืืฉืื ืืื ืืืฉื ืืชืืื ืืช, ืืืชืืื. ืืชืงื ืืื ื ืืกืืืจ ืืช ืืืงืื ืืงืืฆืื ืืืื ืืฉืื ืืืคื.
ืขื ืคื ืืชืงื, ืืฉ ืืืขืืืจ ืืคืืืช ืืจืืขื ืืฉืชื ื ืกืืืื ืืชืืื ืืืช ืฉืืืฉืงื:
- HOME - ืกืคืจืืืช ืืืืช ืฉื ืืืฉืชืืฉ.
- LOGNAME - ืืชืืืจืืช ืืฉืชืืฉ.
- PATH ืืื ืื ืชืื ืฉืื ืืชื ืืืื ืืืฆืื ืืื ืขืืจ ืกืื ืืจืืืื ืืืขืจืืช.
- SHELL - ื ืชืื ืื ืืชืืจืืื ืืคืงืืืืช ืืฉืืืืฉ.
ืืฉ ืืฆืืื, POSIX ืื ืืืืจ ืืืจ ืขื ืืืืื ืืืืขืื ืืขืจืืื ืฉื ืืฉืชื ืื ืืื.
ืื ืืืจ ืืืืชืจ - Vixie cron 3.0pl1
ืืื ืืงืืืื ืืืฉืืชืฃ ืฉื ืืจืกืืืช ืงืจืื ืคืืคืืืจืืืช ืืื Vixie cron 3.0pl1, ืฉืืืฆื ืืจืฉืืืช ืืชืคืืฆื comp.sources.unix ื-1992. ื ืฉืงืื ืืช ืืชืืื ืืช ืืขืืงืจืืืช ืฉื ืืจืกื ืื ืืืชืจ ืคืืจืื.
Vixie cron ืืืืข ืืฉืชื ืชืืื ืืืช (cron ื-crontab). ืืจืืื, ืืืืื ืืืจืื ืขื ืงืจืืื ืืืจืฆื ืฉื ืืฉืืืืช ืืืืืช ืืืฉืืืืช ืฉื ืืืขืจืืช ืืืืืืืืช ืืฉืืืืช ืืฉืชืืฉ ืืืืืืช, ืืืื ืืฉืืจืืช crontab ืืืจืื ืืขืจืืืช ืืืืืืช ืืฉืชืืฉืื.
ืืืืช ืืฉืืืืช ืืงืืฆื ืชืฆืืจื
ืืืืช ืืืฉืืืืช ืฉื ืืฉืชืืฉ-ืขื ืืืืงืืช ื-/etc/crontab. ืืชืืืืจ ืฉื ืืืืช ืืืขืจืืช ืืชืืื ืืชืืืืจ ืฉื Vixie cron, ืืืขื ืฉืืขืืืื ืืฉืืฉืืช ืื ืืฆืืื ืช ืืช ืฉื ืืืฉืชืืฉ ืฉืชืืชืื ืืืฉืืื ืืืคืขืืช:
# ะะฐะฟััะบะฐะตััั ะตะถะตะผะธะฝััะฝะพ ะพั ะฟะพะปัะทะพะฒะฐัะตะปั vlad
* * * * * vlad /path/to/exec
ืืืืืืช ืืฉืืืืช ืืฉืชืืฉ ืจืืืืืช ืืืืงืืืช ื- /var/cron/tabs/username ืืืฉืชืืฉืืช ืืืืชื ืชืืืืจ. ืืืฉืจ ืืชื ืืคืขืื ืืช ืืื ืืฉืืจืืช crontab ืืืฉืชืืฉ, ืืื ืื ืืงืืฆืื ืฉื ืขืจืืื.
ืจืฉืืืืช ืืืฉืชืืฉืื ืขื ืืืฉื ื-crontab ืื ืืืืืช ืืงืืฆืื /var/cron/allow ื-/var/cron/deny, ืฉื ืืชื ืจืง ืฆืจืื ืืืืื ืืช ืฉื ืืืฉืชืืฉ ืืฉืืจื ื ืคืจืืช.
ืชืืืืจ ืืืจืื
ืืืฉืืืื ื- POSIX crontab, ืืคืชืจืื ืฉื Paul Vixey ืืืื ืืกืคืจ ืฉืื ืืืื ืฉืืืืฉืืื ืืืื ืืชืืืืจ ืฉื ืืืืืืช ืืืฉืืืืช ืฉื ืืื ืืฉืืจืืช.
ืชืืืืจ ืืืื ืืืฉ ืืคื ืืืืื: ืืืืืื, ืืชื ืืืื ืืฆืืื ืืืื ืืฉืืืข ืื ืืืืฉืื ืืคื ืฉื (ืฉื ื, ื' ืืื ืืืื):
# ะะฐะฟััะบะฐะตััั ะตะถะตะผะธะฝััะฝะพ ะฟะพ ะฟะพะฝะตะดะตะปัะฝะธะบะฐะผ ะธ ะฒัะพัะฝะธะบะฐะผ ะฒ ัะฝะฒะฐัะต
* * * Jan Mon,Tue /path/to/exec
ืืชื ืืืื ืืฆืืื ืืช ืืฉืื ืฉืื ืืฉืืืืช ืืืฉืงื:
# ะะฐะฟััะบะฐะตััั ั ัะฐะณะพะผ ะฒ ะดะฒะต ะผะธะฝััั
*/2 * * * Mon,Tue /path/to/exec
ื ืืชื ืืขืจืื ืฉืืืื ืืืจืืืืื:
# ะะฐะฟััะบะฐะตััั ั ัะฐะณะพะผ ะฒ ะดะฒะต ะผะธะฝััั ะฒ ะฟะตัะฒัั
ะดะตัััั ะผะธะฝัั ะบะฐะถะดะพะณะพ ัะฐัะฐ
0-10/2 * * * * /path/to/exec
ืืืืคืืช ืืื ืืืืืืืืืืช ืืชืืืืจ ืืจืืื ื ืชืืืืช (ืืชืืื ืืืืฉ, ืฉื ืชื, ืฉื ืชื, ืืืืฉื, ืฉืืืขื, ืืืื, ืืฆืืช, ืฉืขื):
# ะะฐะฟััะบะฐะตััั ะฟะพัะปะต ะฟะตัะตะทะฐะณััะทะบะธ ัะธััะตะผั
@reboot /exec/on/reboot
# ะะฐะฟััะบะฐะตััั ัะฐะท ะฒ ะดะตะฝั
@daily /exec/daily
# ะะฐะฟััะบะฐะตััั ัะฐะท ะฒ ัะฐั
@hourly /exec/daily
ืกืืืืช ืืืฆืืข ืืฉืืืืช
Vixie cron ืืืคืฉืจ ืื ืืฉื ืืช ืืช ืกืืืืช ืืืคืขืื ืฉื ืืืฉืืืื.
ืืฉืชื ื ืืกืืืื USER, LOGNAME ื-HOME ืืื ื ืืกืืคืงืื ืจืง ืขื ืืื ืืืืื, ืืื ืืงืืืื ืืงืืืฅ
ืืฉืชื ื ืกืืืื ืืกืืืืื (ืืขืืงืจ SHELL ื-HOME) ืืฉืืฉืื ืืช cron ืขืฆืื ืืืคืขืืช ืืืฉืืื. ืื ืขืฉืื ืืืืจืืืช ืฉืืืืฉ ื-bash ืืืงืื ื-sh ืจืืื ืืืคืขืืช ืืฉืืืืช ืืืชืืืืช ืืืฉืืช:
SHELL=/bin/bash
HOME=/tmp/
# exec ะฑัะดะตั ะทะฐะฟััะตะฝ bash-ะตะผ ะฒ /tmp/
* * * * * /path/to/exec
ืืกืืคื ืฉื ืืืจ, ืื ืืฉืชื ื ืืกืืืื ืืืืืืจืื ืืืืื (ืืฉืืืืฉ ืขื ืืื cron ืื ืืืจืืฉืื ืืชืืืื) ืืืขืืจื ืืืฉืืื ืืคืืขืืช.
ืืื ืืขืจืื ืงืืฆืื, crontab ืืฉืชืืฉ ืืขืืจื ืฉืฆืืื ืืืฉืชื ื ืืกืืืื VISUAL ืื EDITOR. ืื ืืกืืืื ืฉืื ืืืฆืขื crontab ืื ืืืืืจืื ืืช ืืืฉืชื ืื ืืืื, ืื ื ืขืฉื ืฉืืืืฉ ื-"/usr/ucb/vi" (ucb ืืื ืื ืจืื ืืื ืืืจืกืืืช ืงืืืคืืจื ืื, ืืจืงืื).
cron ืขื ืืืืื ืืืืืื ืื
ืืืคืชืืื ืฉื Debian ืืืคืฆืืช ื ืืืจืืช ืคืจืกืื
ืฉืื ืืืื ืคืืืช ืืืืืื ืื ืืืืฉืืื ืืืืืื ืืช ืืืืงืื ืฉื ืงืืฆื ืชืฆืืจื ืืืืืืืช ืืฉืืืืช.
ืืืืืืช ืืฉืชืืฉ ืืืืืื ืืืืงืืืช ืืกืคืจืืืช /var/spool/cron/crontabs, ืืืืช ืืืขืจืืช ืขืืืื ืฉื - ื- /etc/crontab. ืืืืืืช ืืฉืืืืช ืกืคืฆืืคืืืช ืืืืืืืช ืืืืื ืืืืงืืืช ื-/etc/cron.d, ืืฉื ืืืื ื-cron ืงืืจื ืืืชื ืืืืืืืืช. ืืงืจืช ืืืฉืช ืืืฉืชืืฉ ื ืฉืืืช ืขื ืืื ืืงืืฆืื /etc/cron.allow ื-/etc/cron.deny.
ืืขืืคืช ืืจืืจืช ืืืืื ืืื ืขืืืื /bin/sh, ืืฉืจ ืืืืืื ืืื ืืขืืคืช ืงืื ื ืชืืืืช POSIX
Cron ืขืฆืื ืืืจืกืืืช ืืืืจืื ืืช ืฉื ืืืืื ืืืฉืง ืืืืฆืขืืช systemd, ืื ืืชื ืืจืืืช ืืช ืชืฆืืจืช ืืืฉืงื ื-/lib/systemd/system/cron.service. ืืื ืฉืื ืืืจ ืืืืื ืืชืฆืืจืช ืืฉืืจืืช; ืื ื ืืืื ืืฉืืืืช ืขืืื ืืืชืจ ืืืื ืืืชืืฆืข ืืืืฆืขืืช ืืฉืชื ื ืกืืืื ืืืืฆืืจืื ืืฉืืจืืช ื-crontab ืฉื ืื ืืฉืชืืฉ.
ืืงืืจื ื-RedHat, Fedora ื- CentOS
ืชืฆืืจืช ืืจืืจืช ืืืืื ืืื ืืืงืืืืช ืืจืืืืื: ืืืืช ืืืขืจืืช ื ืืฆืืช ื-/etc/crontab, ืืืืืืช ืฉืืืช ืืช ืืืืืืืช ืฉืืื ื-/etc/cron.d, ืืืืืืช ืืฉืชืืฉ ื ืื ืกืืช ื-/var/spool/cron/crontabs.
ืืืืื ืคืืขื ืชืืช ืืงืจืช ืืขืจืืช, ืชืฆืืจืช ืืฉืืจืืช ืืื /lib/systemd/system/crond.service.
ืืืคืฆืืช ืืืืืืช Red Hat, /bin/sh ืืฉืืฉ ืืืจืืจืช ืืืื ืืขืช ืืืคืขืื, ืฉืืื ื-bash ืืกืื ืืจืื. ืืฉ ืืฆืืื ืื ืืขืช ืืคืขืืช ืืฉืืืืช cron ืืจื /bin/sh, ืืขืืคืช ื-bash ืืชืืืื ืืืฆื ืชืืื POSIX ืืืื ื ืงืืจืืช ืื ืชืฆืืจื ื ืืกืคืช, ืคืืขืืช ืืืฆื ืื ืืื ืืจืืงืืืื.
ืืงืืจื ื-SLES ืื-openSUSE
ืืืคืฆื ืืืจืื ืืช SLES ืืื ืืืจืช ืฉืื openSUSE ืืฉืชืืฉืืช ืืืืชื ืืงืืจื. ืืืืื ืืื ืืืคืขื ืื ืชืืช systemd, ืชืฆืืจืช ืืฉืืจืืช ืืืืงืืช ื- /usr/lib/systemd/system/cron.service. ืชืฆืืจื: /etc/crontab, /etc/cron.d, /var/spool/cron/tabs. /bin/sh ืืื ืืืชื bash ืืคืืขื ืืืฆื ืื ืืื ืืจืืงืืืื ืชืืื POSIX.
ืืืฉืืจ Vixie cron
ืฆืืฆืืื ืืืืืจื ืืื ืฉื cron ืื ืืฉืชื ื ืืืืคื ืงืืฆืื ื ืืืฉืืืื ื-Vixie cron, ืื ืขืืืื ืจืืฉื ืชืืื ืืช ืืืฉืืช ืฉืืื ื ื ืืจืฉืืช ืืื ืืืืื ืืช ืขืงืจืื ืืช ืืชืืื ืืช. ืจืืื ืืืืจืืืืช ืืืื ืืขืืฆืืืช ืืฆืืจื ืืจืืขื ืืืืืืืืช ืืช ืืงืื. ืชืขื ืื ืืงืจืื ืืช ืงืื ืืงืืจ ืืงืจืื ืืืงืืจื ืืืช ืคืื ืืืงืกื.
ืืื, ืืืืืชื ืื ืชื ืืช ืืืฉืืจ ื-cron ืืืืฆืขืืช ืืืืืื ืฉื ืชืืื ืืช cron ืืืฉืืชืคืช ืืฉื ื ืขื ืคื ืืคืืชืื - Vixie cron 3.0pl1. ืื ื ืืคืฉื ืืช ืืืืืืืืช ืขื ืืื ืืกืจืช ifdefs ืฉืืกืืืื ืืช ืืงืจืืื ืืืฉืืืช ืคืจืืื ืงืื ืื.
ื ืืชื ืืืืง ืืช ืขืืืืช ืืฉื ืืืกืคืจ ืฉืืืื:
- ืืชืืื ืืชืืื ืืช.
- ืืืกืืฃ ืืขืืืื ืจืฉืืืช ืืืฉืืืืช ืืืคืขืื.
- ืืืืืช ืงืจืื ืจืืฉืืช ืคืืขืืช.
- ืืชืื ืืฉืืื.
ืืืื ื ืกืชืื ืขืืืื ืืคื ืืกืืจ.
ืืชืืื
ืืืฉืจ ืืชืืืืื, ืืืืจ ืืืืงืช ืืจืืืื ืื ืืชืืืื, cron ืืชืงืื ืืช ืืืคืื ืืืืชืืช SIGCHLD ื-SIGHUP. ืืจืืฉืื ืขืืจื ืจืืฉืื ืืืืื ืืืื ืกืืื ืชืืืื ืืฆืืฆื, ืืฉื ื ืกืืืจ ืืช ืืชืืจ ืืงืืืฅ ืฉื ืงืืืฅ ืืืืื:
signal(SIGCHLD, sigchld_handler);
signal(SIGHUP, sighup_handler);
ื-cron daemon ืชืืื ืคืืขื ืืื ืขื ืืืขืจืืช, ืจืง ืืชืืจ ืืฉืชืืฉ-ืขื ืืืชืืงืืืช ื-cron ืืจืืฉืืช. ืืฉืืืืช ืืืืืช ืืืฆืจืืช ืงืืืฅ ื ืขืืื ืขื ื-PID ืฉื ืชืืืื ืืืืื, ืืื ืฉืืืฉืชืืฉ ื ืืื ืืฉื ื ืืช ืืกืคืจืืื ืื ืืืืืช ืืกืคืจืืื ืืจืืฉืืช:
acquire_daemonlock(0);
set_cron_uid();
set_cron_cwd();
ื ืชืื ืืจืืจืช ืืืืื ืืืืืจ, ืืฉืจ ืืฉืืฉ ืืขืช ืืชืืืช ืชืืืืืื:
setenv("PATH", _PATH_DEFPATH, 1);
ืืืืจ ืืื ืืชืืืื ืขืืืจ "ืืืื ืืืฆืื": ืืื ืืืฆืจ ืขืืชืง ืฆืืฆื ืฉื ืืชืืืื ืขื ืืื ืงืจืืื ืืคืืจืง ืืืคืขืื ืืืฉื ืืชืืืื ืืืื (ืงืจืืืช setsid). ืชืืืื ืืืืจื ืืื ื ื ืืืฅ ืขืื ืืืื ืืืฆื:
switch (fork()) {
case -1:
/* ะบัะธัะธัะตัะบะฐั ะพัะธะฑะบะฐ ะธ ะทะฐะฒะตััะตะฝะธะต ัะฐะฑะพัั */
exit(0);
break;
case 0:
/* ะดะพัะตัะฝะธะน ะฟัะพัะตัั */
(void) setsid();
break;
default:
/* ัะพะดะธัะตะปััะบะธะน ะฟัะพัะตัั ะทะฐะฒะตััะฐะตั ัะฐะฑะพัั */
_exit(0);
}
ืกืืื ืชืืืื ืืื ืืฉืืจืจ ืืช ืื ืขืืื ืืงืืืฅ ืื ืขืืื. ืื ืืกืฃ, ื ืืจืฉ ืืขืืื ืืช ื-PID ืืงืืืฅ ืืืื. ืืืืจ ืืื, ืืืืืื ืืช ืืกื ืื ืชืื ืื ืฉื ืืืฉืืืืช:
/* ะฟะพะฒัะพัะฝัะน ะทะฐั
ะฒะฐั ะปะพะบะฐ */
acquire_daemonlock(0);
/* ะะฐะฟะพะปะฝะตะฝะธะต ะะ */
database.head = NULL;
database.tail = NULL;
database.mtime = (time_t) 0;
load_database(&database);
ืืื ืงืจืื ืขืืืจ ืืืืืืจ ืืขืืืื ืืจืืฉื. ืืื ืืคื ื ืื, ืืืื ืืืฆืืฅ ืืืขืื ืช ืจืฉืืืช ืืืฉืืืืช.
ืืืกืืฃ ืืขืืืื ืจืฉืืืช ืืืฉืืืืช
ืืคืื ืงืฆืื load_database ืืืจืืืช ืืืขืื ืช ืจืฉืืืช ืืืฉืืืืช. ืื ืืืืง ืืช ืืงืจืื ืืื ืืจืืฉื ืฉื ืืืขืจืืช ืืืช ืืกืคืจืืื ืขื ืงืืฆื ืืืฉืชืืฉ. ืื ืืงืืฆืื ืืืกืคืจืืื ืื ืืฉืชื ื, ืจืฉืืืช ืืืฉืืืืช ืื ืชืืงืจื ืืืืฉ. ืืืจืช, ืจืฉืืื ืืืฉื ืฉื ืืฉืืืืช ืืชืืืื ืืืืืืฆืจ.
ืืขืื ืช ืงืืืฅ ืืขืจืืช ืขื ืฉืืืช ืงืืฆืื ืืืืืืืช ืืืืืืื:
/* ะตัะปะธ ัะฐะนะป ัะธััะตะผะฝะพะน ัะฐะฑะปะธัั ะธะทะผะตะฝะธะปัั, ะฟะตัะตัะธััะฒะฐะตะผ */
if (syscron_stat.st_mtime) {
process_crontab("root", "*system*",
SYSCRONTAB, &syscron_stat,
&new_db, old_db);
}
ืืขืื ืช ืืืืืืช ืืฉืชืืฉืื ืืืืืื:
while (NULL != (dp = readdir(dir))) {
char fname[MAXNAMLEN+1],
tabname[MAXNAMLEN+1];
/* ัะธัะฐัั ัะฐะนะปั ั ัะพัะบะพะน ะฝะต ะฝะฐะดะพ*/
if (dp->d_name[0] == '.')
continue;
(void) strcpy(fname, dp->d_name);
sprintf(tabname, CRON_TAB(fname));
process_crontab(fname, fname, tabname,
&statbuf, &new_db, old_db);
}
ืืืืจ ืืื ืืกื ืื ืชืื ืื ืืืฉื ืืืืืฃ ืืืืฉ.
ืืืืืืืืช ืฉืืืขืื, ืืงืจืืื ืืคืื ืงืฆืื process_crontab ืืืืชืช ืฉืงืืื ืืฉืชืืฉ ืืชืืื ืืฉื ืงืืืฅ ืืืืื (ืืื ืื ืืื ืืฉืชืืฉ-ืขื) ืืืืืจ ืืื ืงืืจื ื-load_user. ืืืืจืื ืืืจ ืงืืจื ืืช ืืงืืืฅ ืขืฆืื ืฉืืจื ืืืจ ืฉืืจื:
while ((status = load_env(envstr, file)) >= OK) {
switch (status) {
case ERR:
free_user(u);
u = NULL;
goto done;
case FALSE:
e = load_entry(file, NULL, pw, envp);
if (e) {
e->next = u->crontab;
u->crontab = e;
}
break;
case TRUE:
envp = env_set(envp, envstr);
break;
}
}
ืืื, ืื ืฉืืฉืชื ื ืืกืืืื ืืืืืจ (ืฉืืจืืช ืืฆืืจืช VAR=value) ืืืืฆืขืืช ืืคืื ืงืฆืืืช load_env / env_set, ืื ืฉืชืืืืจ ืืืฉืืื ื ืงืจื (* * * * * /path/to/exec) ืืืืฆืขืืช ืืคืื ืงืฆืื load_entry.
ืืฉืืช ืืื ืืกื ืฉืืืืืจื load_entry ืืื ืืืฉืืื ืฉืื ื, ืฉืืืืงืืช ืืจืฉืืืช ืืืฉืืืืช ืืืืืืช. ืืคืื ืงืฆืื ืขืฆืื ืืืฆืขืช ื ืืชืื ืืืืืื ืฉื ืคืืจืื ืืืื, ืื ืื ื ืืขืื ืืื ืื ืืืชืจ ืืืฆืืจืช ืืฉืชื ื ืกืืืื ืืคืจืืืจืื ืฉื ืืฉืงืช ืืฉืืืืช:
/* ะฟะพะปัะทะพะฒะฐัะตะปั ะธ ะณััะฟะฟะฐ ะดะปั ะทะฐะฟััะบะฐ ะทะฐะดะฐัะธ ะฑะตััััั ะธะท passwd*/
e->uid = pw->pw_uid;
e->gid = pw->pw_gid;
/* ัะตะปะป ะฟะพ ัะผะพะปัะฐะฝะธั (/bin/sh), ะตัะปะธ ะฟะพะปัะทะพะฒะฐัะตะปั ะฝะต ัะบะฐะทะฐะป ะดััะณะพะต */
e->envp = env_copy(envp);
if (!env_get("SHELL", e->envp)) {
sprintf(envstr, "SHELL=%s", _PATH_BSHELL);
e->envp = env_set(e->envp, envstr);
}
/* ะดะพะผะฐัะฝัั ะดะธัะตะบัะพัะธั */
if (!env_get("HOME", e->envp)) {
sprintf(envstr, "HOME=%s", pw->pw_dir);
e->envp = env_set(e->envp, envstr);
}
/* ะฟััั ะดะปั ะฟะพะธัะบะฐ ะฟัะพะณัะฐะผะผ */
if (!env_get("PATH", e->envp)) {
sprintf(envstr, "PATH=%s", _PATH_DEFPATH);
e->envp = env_set(e->envp, envstr);
}
/* ะธะผั ะฟะพะปัะทะพะฒัะตะปั ะฒัะตะณะดะฐ ะธะท passwd */
sprintf(envstr, "%s=%s", "LOGNAME", pw->pw_name);
e->envp = env_set(e->envp, envstr);
ืืืืืื ืืจืืฉืืช ืคืืขืืช ืขื ืจืฉืืืช ืืืฉืืืืช ืื ืืืืืช.
ืืืืื ืจืืฉืืช
ืืงืจืื ืืืงืืจื ืืืจืกื 7 Unix ืขืื ืื ืคืฉืื: ืืื ืงืจื ืืืืฉ ืืช ืืชืฆืืจื ืืืืืื, ืืฉืืง ืืช ืืืฉืืืืช ืฉื ืืืงื ืื ืืืืืช ืืืฉืชืืฉ-ืขื, ืืืฉื ืขื ืชืืืืช ืืืงื ืืืื. ืืืฉื ืคืฉืืื ืื ืืืืื ืืช ืืฉื ืืช ืืจืฉื ืืฉืืืื ืจืืื ืืื.
ืืืฆืขื ืืจืกื ืืืืคืืช ื-SysV, ืฉืื ืืืืื ืืื ืืืฉืื ืื ืขื ืืืงื ืืงืจืืื ืขืืืจื ืืืืืจื ืืืฉืืื, ืื ืืืฉื 30 ืืงืืช. ืคืืืช ืืฉืืืื ื ืฆืจืื ืืงืจืืื ืืืืจืช ืฉื ืืชืฆืืจื ืืืืืงืช ืืฉืืืืช ืืืฆื ืื, ืื ืขืืืื ืืืืจ ืฉื ืจืฉืืืช ืืืฉืืืืช ืืคื ืืืืชื ื ืื.
Vixie cron ืืืจื ืืืืืง ืจืฉืืืืช ืืฉืืืืช ืคืขื ืืืงื, ืืืจืื ืืืื ืขื ืกืืฃ ืฉื ืืช ื-80 ืืื ืืจืื ืืืชืจ ืืฉืืืื ืืืืื ืืช Unix ืกืื ืืจืืืืช:
/* ะฟะตัะฒะธัะฝะฐั ะทะฐะณััะทะบะฐ ะทะฐะดะฐั */
load_database(&database);
/* ะทะฐะฟัััะธัั ะทะฐะดะฐัะธ, ะฟะพััะฐะฒะปะตะฝะฝัะต ะบ ะฒัะฟะพะปะฝะตะฝะธั ะฟะพัะปะต ะฟะตัะตะทะฐะณััะทะบะธ ัะธััะตะผั */
run_reboot_jobs(&database);
/* ัะดะตะปะฐัั TargetTime ะฝะฐัะฐะปะพะผ ะฑะปะธะถะฐะนัะตะน ะผะธะฝััั */
cron_sync();
while (TRUE) {
/* ะฒัะฟะพะปะฝะธัั ะทะฐะดะฐัะธ, ะฟะพัะปะต ัะตะณะพ ัะฟะฐัั ะดะพ TargetTime ั ะฟะพะฟัะฐะฒะบะพะน ะฝะฐ ะฒัะตะผั, ะฟะพััะฐัะตะฝะฝะพะต ะฝะฐ ะทะฐะดะฐัะธ */
cron_sleep();
/* ะฟะตัะตัะธัะฐัั ะบะพะฝัะธะณััะฐัะธั */
load_database(&database);
/* ัะพะฑัะฐัั ะทะฐะดะฐัะธ ะดะปั ะดะฐะฝะฝะพะน ะผะธะฝััั */
cron_tick(&database);
/* ะฟะตัะตะฒะตััะธ TargetTime ะฝะฐ ะฝะฐัะฐะปะพ ัะปะตะดัััะตะน ะผะธะฝััั */
TargetTime += 60;
}
ืคืื ืงืฆืืืช cron_sleep ืืขืืจืืช ืืฉืืจืืช ืืืืฆืืข ืืฉืืืืช, ืงืจืืื ืืคืื ืงืฆืืืช job_runqueue (enumerate and run tasks) ื-do_command (ืืคืขื ืื ืืฉืืื ืืืืืช). ืืช ืืคืื ืงืฆืื ืืืืจืื ื ืืืื ืืืืื ืืืชืจ ืคืืจืื.
ืืคืขืืช ืืฉืืื
ืืคืื ืงืฆืื do_command ืืืืฆืขืช ืืกืื ืื Unix ืืื, ืืืืืจ, ืืื ืขืืฉื ืืืื ืืื ืืืฆืข ืืช ืืืฉืืื ืืืืคื ืืกืื ืืจืื ื. ืชืืืื ืืืืจื ืืืฉืื ืืืฉืืง ืืฉืืืืช, ืชืืืื ืืืื ืืืื ืืช ืชืืืื ืืืฉืืืืช:
switch (fork()) {
case -1:
/*ะฝะต ัะผะพะณะปะธ ะฒัะฟะพะปะฝะธัั fork */
break;
case 0:
/* ะดะพัะตัะฝะธะน ะฟัะพัะตัั: ะฝะฐ ะฒััะบะธะน ัะปััะฐะน ะตัะต ัะฐะท ะฟัะพะฑัะตะผ ะทะฐั
ะฒะฐัะธัั ะณะปะฐะฒะฝัะน ะปะพะบ */
acquire_daemonlock(1);
/* ะฟะตัะตั
ะพะดะธะผ ะบ ัะพัะผะธัะพะฒะฐะฝะธั ะฟัะพัะตััะฐ ะทะฐะดะฐัะธ */
child_process(e, u);
/* ะฟะพ ะทะฐะฒะตััะตะฝะธั ะดะพัะตัะฝะธะน ะฟัะพัะตัั ะทะฐะบะฐะฝัะธะฒะฐะตั ัะฐะฑะพัั */
_exit(OK_EXIT);
break;
default:
/* ัะพะดะธัะตะปััะบะธะน ะฟัะพัะตัั ะฟัะพะดะพะปะถะฐะตั ัะฐะฑะพัั */
break;
}
ืืฉ ืื ืืจืื ืืืืืื ื-child_process: ืืื ืืืงื ืืขืฆืื ืืจืื ืคืื ืืฉืืืืืช ืกืื ืืจืืืื, ืืื ืืฉืืื ืืืชื ืืืืืจ (ืื ืืฉืชื ื ืืกืืืื MAILTO ืืฆืืื ืืืืืช ืืืฉืืืืช), ืืืืกืืฃ, ืืืชืื ื-main ืชืืืื ืืฉืืืช ืืืฉืืื.
ืชืืืื ืืืฉืืื ื ืืฆืจ ืขื ืืื ืืืื ื ืืกืฃ:
switch (vfork()) {
case -1:
/* ะฟัะธ ะพัะธะฑะบะธ ััะฐะทั ะทะฐะฒะตััะฐะตััั ัะฐะฑะพัะฐ */
exit(ERROR_EXIT);
case 0:
/* ะฟัะพัะตัั-ะฒะฝัะบ ัะพัะผะธััะตั ะฝะพะฒัั ัะตััะธั, ัะตัะผะธะฝะฐะป ะธ ั.ะด.
*/
(void) setsid();
/*
* ะดะฐะปััะต ะผะฝะพะณะพัะปะพะฒะฝะฐั ะฝะฐัััะพะนะบะฐ ะฒัะฒะพะดะฐ ะฟัะพัะตััะฐ, ะพะฟัััะธะผ ะดะปั ะบัะฐัะบะพััะธ
*/
/* ัะผะตะฝะฐ ะดะธัะตะบัะพัะธะธ, ะฟะพะปัะทะพะฒะฐัะตะปั ะธ ะณััะฟะฟั ะฟะพะปัะทะพะฒะฐัะตะปั,
* ัะพ ะตััั ะฟัะพัะตัั ะฑะพะปััะต ะฝะต ััะฟะตัะฟะพะปัะทะพะฒะฐัะตะปััะบะธะน
*/
setgid(e->gid);
setuid(e->uid);
chdir(env_get("HOME", e->envp));
/* ะทะฐะฟััะบ ัะฐะผะพะน ะบะพะผะฐะฝะดั
*/
{
/* ะฟะตัะตะผะตะฝะฝะฐั ะพะบััะถะตะฝะธั SHELL ัะบะฐะทัะฒะฐะตั ะฝะฐ ะธะฝัะตัะฟัะตัะฐัะพั ะดะปั ะทะฐะฟััะบะฐ */
char *shell = env_get("SHELL", e->envp);
/* ะฟัะพัะตัั ะทะฐะฟััะบะฐะตััั ะฑะตะท ะฟะตัะตะดะฐัะธ ะพะบััะถะตะฝะธั ัะพะดะธัะตะปััะบะพะณะพ ะฟัะพัะตััะฐ,
* ัะพ ะตััั ะธะผะตะฝะฝะพ ัะฐะบ, ะบะฐะบ ะพะฟะธัะฐะฝะพ ะฒ ัะฐะฑะปะธัะต ะทะฐะดะฐั ะฟะพะปัะทะพะฒะฐัะตะปั */
execle(shell, shell, "-c", e->cmd, (char *)0, e->envp);
/* ะพัะธะฑะบะฐ โ ะธ ะฟัะพัะตัั ะฝะฐ ะทะฐะฟัััะธะปัั? ะทะฐะฒะตััะตะฝะธะต ัะฐะฑะพัั */
perror("execl");
_exit(ERROR_EXIT);
}
break;
default:
/* ัะฐะผ ะฟัะพัะตัั ะฟัะพะดะพะปะถะฐะตั ัะฐะฑะพัั: ะถะดะตั ะทะฐะฒะตััะตะฝะธั ัะฐะฑะพัั ะธ ะฒัะฒะพะดะฐ */
break;
}
ืื ืืขืฆื ืื ืื ืฉ-cron ืืื. ืืฉืืืชื ืืื ืคืจืืื ืืขื ืืื ืื, ืืืฉื, ืืชืืฉืื ืืช ืืืฉืชืืฉืื ืืจืืืงืื, ืืื ืฆืืื ืชื ืืช ืืขืืงืจ.
ืืืจืืช ืืืจ
Cron ืืื ืชืืื ืืช ืคืฉืืื ืืฉืืืืฉืืช ืืืคืชืืข, ืฉื ืขืฉืชื ืืืืื ืืืกืืจืืช ืฉื ืขืืื ืืื ืืงืก. ืืื ืื ืขืืฉื ืฉืื ืืืจ ื ืืกืฃ, ืืื ืืื ืขืืฉื ืืช ืืขืืืื ืฉืื ื ืคืื ืืืจ ืืื ืขืฉืืจืื. ืืขืืจืช ืืงืื ืืืจืกื ืฉืืืืขื ืขื ืืืืื ืื ืืจืื ืื ืืืชืจ ืืฉืขื, ืืืื ืื ืืืฃ ืืืื! ืื ื ืืงืืื ืฉืืฆืืืชื ืืืืืง ืืช ืื ืืืชื.
ืื ื ืื ืืืืข ืื ืืืชืื, ืืื ืงืฆืช ืขืฆืื ืื ืืืืื ืฉืชืื ืืช ืืืืจื ืืืช, ืขื ืื ืืืื ืฉืื ืืกืื ืืชืจ ืืืคืฉืืืช ืืชืจ ืขื ืืืืื, ืื ืืืขืืื ืืคืฉืืืช ืืื ืืืฉื ืืื ืจื.
ืืฉื ื ืืืืจื ืืืืืช ืืืืจื ืืืช ืจืืืช ื-cron: ืืขืจืืช ืืืืืจืื ืืืคืฉืจืื ืื ืืืจืื ืืขืจืืืช ืืืจืืืืช ืขื ืชืืืช, fcron ืืืคืฉืจืช ืืืืกืช ืืฆืืจื ืืืืฉื ืืืชืจ ืืช ืฆืจืืืช ืืืฉืืืื ืืคื ืืฉืืืืช. ืืื ืืืืคื ืืืฉื, ืืงืจืื ืืื ืืคืฉืื ืืืืชืจ ืชืืื ืืกืคืืง ืื.
ืืงืืฆืืจ, ืืืื ืืช ืืื ืืงืก, ืืฉืชืืฉื ืืชืืื ืืช ืคืฉืืืืช ืืื ืชืฉืืื ืืงืจืื ืืช ืืืื ื ืืคืืืคืืจืื ืฉืืื!
ืืงืืจ: www.habr.com