크론

cron
크론
Cron-example-command.gif
사용 예cron효용.
개발자AT&T 벨 연구소
초기 릴리즈1975년 5월, 47년 전(1975-05)
기입처C
운영 체제Unix 및 Unix와 유사한 Plan 9, Inferno
유형작업 스케줄러

명령줄 유틸리티는 Unix유사한 운영 체제의 작업 스케줄러입니다.소프트웨어 환경을 설정하고 관리하는 사용자는 cron을 사용하여 cron [2][3]작업이라고도 하는 작업(명령어 또는스크립트)을 일정 시간, 날짜 또는 [4]간격으로 정기적으로 실행하도록 스케줄링합니다[1].일반적으로 시스템 유지보수 또는 관리를 자동화합니다.다만, 범용성이 있기 때문에 인터넷에서 파일을 다운로드하거나 정기적으로 [5]이메일을 다운로드 할 때 편리합니다.

Cron은 반복 작업을 스케줄링하는 데 가장 적합합니다.일회성 태스크 스케줄은 관련 at 유틸리티를 사용하여 수행할 수 있습니다.

크론 이름은 그리스어로 [6][better source needed]시간을 뜻하는 크로노스(Chronos)에서 유래했습니다.

개요

cron 액션은 crontab(cron 테이블) 파일에 의해 구동됩니다.cron 파일은 특정 일정에 따라 정기적으로 셸 명령을 실행하는 설정 파일입니다.crontab 파일은 cron 데몬에 대한 작업 및 기타 명령 목록이 저장된 위치에 저장됩니다.사용자는 개별 crontab 파일을 가질 수 있으며 시스템 전체의 crontab 파일이 있는 경우가 많습니다(일반적으로/etc또는 의 서브디렉토리/etc예./etc/cron.d시스템 관리자만 [note 1]편집할 수 있습니다.

crontab 파일의 각 행은 작업을 나타내며 다음과 같습니다.

#┌─────────────분(0-59))│┌─────────────시간(0-23)#│ 그 달│┌───────────── 날(1-31)#│││┌───────────── 달(1-12)#│ │ │ 이번 주│┌───────────── 날(0-6)(일요일부터 토요일에,#││ │ │의 일부 시스템에 │ 7은 또한 일요일)#│ │ │ │ │ # │ │ │ │ │ #*******<>명령 t.eOOOxecute >

각 행의 구문에서는 명령어 실행 시간을 나타내는5개의 필드로 이루어진 cron 식과 그 후에 셸 명령어가 실행되어야 합니다.

일반적으로 시간/날짜 지정 필드가 모두 현재 시간과 날짜와 일치할 때 작업이 실행되지만 한 가지 예외가 있습니다. 즉, "day of month"(필드 3)와 "day of week"(필드 5)가 모두 제한되는 경우("*"를 포함하지 않음) 또는 둘 다 현재 [7]날짜와 일치해야 합니다.

예를 들어 cron 사용자의 기본 셸이 Bourne 쉘에 준거하고 있다고 가정하면 다음 명령어는 매일 0시(00:01) 1분 경과 시 Apache 에러 로그를 클리어합니다.

1 0 * * printf " > / var / log / error _ log

이 예에서는 매주 토요일 23:45(11:45 PM)에 export_dump.sh라는 셸 프로그램을 실행합니다.

45 23 * * 6 / home / facebook / export _ facebooks . sh

주의: 일부 시스템에서는 다음을 지정할 수도 있습니다.*/nn번째 시간 간격마다 실행됩니다.또한 여러 특정 시간 간격을 쉼표로 지정할 수 있습니다(예:1,2,3다음 예에서는 첫 번째, 두 번째 및 세 번째 시간(즉, 01:00, 01:05, 01:10, 03:55까지)마다 5분마다 명령줄에 "hello world"를 출력합니다.

*/5 1, 2, 3 * * * 에코 헬로 월드

사용자의 컨피규레이션파일은, 다음의 콜에 의해서 편집할 수 있습니다.crontab -e실제 구현에서 이 파일을 저장하는 위치에 관계없이 사용할 수 있습니다.

몇개cronPaul Vixie에 의해 작성되어 많은 Linux 디스트리뷰션에 포함되어 있는 일반적인4번째 BSD 에디션과 같은 구현에서는 여섯 번째 필드, 즉 지정된 작업(사용자 존재 및 권한에 따라 다름)을 실행하는 계정 사용자 이름을 추가합니다.이것은 시스템 crontab에서만 허용되며, 각각을 설정하는 단일 사용자에게 할당되는 다른 탭에서는 허용되지 않습니다.6번째 필드는 계정 사용자 이름 대신 년도 동안 사용될 수 있습니다.Windows 용 nncron 데몬이 이를 수행합니다.

cron의 Amazon EventBridge 실장에서는 요일0이 아니라 요일0이 아니라 1-7의 SUN-SAT(0-6이 아니라)를 사용하고 있으며 첫 번째 주 및 마지막 날 등의 추가 표현 기능을 지원합니다.[8]

미리 정의된 비표준 스케줄링 정의

일부 cron[9] 실장에서는 다음과 같은 비표준 매크로가 지원됩니다.

엔트리 묘사 등가
@yearly(또는@annually) 1년 1월 1일 자정에 1회 실행 0 0 1 1 *
@monthly 매월 1회 매월 1일 0시에 실행 0 0 1 * *
@weekly 주 1회 일요일 오전 0시에 실행 0 0 * * 0
@daily(또는@midnight) 매일 자정 1회 실행 0 0 * * *
@hourly 1시간에 1회 시간 초에 실행 0 * * * *
@reboot 시작 시 실행

@reboot는 데몬이 시작될 때 작업을 한 번 실행하도록 설정합니다.cron은 일반적으로 재시작되지 않으므로 이는 일반적으로 부팅 중인 시스템에 해당합니다.이 동작은 Debian에서 [10]제공되는 것과 같은 cron의 일부 변형에서 적용되므로 단순히 데몬을 재시작하는 것만으로는 재실행되지 않습니다.@reboot작업을 수행합니다.

@reboot는, 특정의 유저아래에서 서버 또는 데몬을 기동할 필요가 있어, 유저가 프로그램을 기동하기 위해서 init 를 설정할 수 없는 경우에 편리합니다.

Cron 권한

이들 2개의 파일은 중요한 역할을 합니다.

  • /etc/cron.allow - 이 파일이 존재하는 경우 cron 작업을 사용할 수 있도록 해당 사용자의 이름을 포함해야 합니다.
  • /etc/cron.deny - cron.allow 파일이 존재하지 않지만 /etc/cron.deny 파일이 존재하는 경우 cron 작업을 사용하려면 /etc/cron.deny 파일에 사용자가 나열되지 않아야 합니다.

이러한 파일이 존재하지 않는 경우 사이트 의존 설정 파라미터에 따라서는 슈퍼 사용자만 cron 작업을 사용할 수 있거나 모든 사용자가 cron 작업을 사용할 수 있습니다.

시간대 처리

대부분의 cron 실장에서는 cron 데몬이 실행되는 시스템타임존 설정의 crontab 엔트리를 해석하기만 하면 됩니다.대규모 멀티 유저 머신의 유저가 복수의 타임 존에 있는 경우, 특히 시스템 디폴트타임 존에 혼란을 줄 가능성이 있는 DST가 포함되어 있는 경우, 이것은 논란의 원인이 될 수 있습니다.따라서 cron 실장에서는 특별한 경우로 사용자 crontab에서 "CRON_TZ=<time zone>" 형식의 행을 인식하고 해당 시간대에 [11]관련된 후속 crontab 엔트리를 해석할 수 있습니다.

역사

초기 버전

버전 7 Unix의 cron은 시스템서비스(나중에 데몬이라고 불림)에서 호출된 것입니다./etc/rcoperating system이 멀티 유저 [12]모드로 이행했을 때.알고리즘은 간단했습니다.

  1. 읽어주세요/usr/lib/crontab[13]
  2. 현재 날짜와 시각에 실행할 필요가 있는 명령어가 있는지 여부를 판단하고, 실행할 필요가 있는 경우 해당 명령어를 superuser, root로 실행합니다.
  3. 1분간 자다
  4. 순서 1부터 반복합니다.

이 버전의 cron은 기본적이고 견고하지만 작업을 찾든 찾지 못하든 리소스를 소비합니다.1970년대 후반 Purdue University에서 시분할 VAX를 통해 cron's 서비스를 100명의 모든 사용자로 확장하는 실험에서 시스템에 너무 많은 부하를 가하는 것으로 나타났습니다.

다중 사용자 기능

다음 버전의 cron은 Unix System V 릴리즈와 함께 슈퍼유저뿐만 아니라 Unix 시스템의 모든 사용자에게 cron 기능을 확장하기 위해 작성되었습니다.강력한 프로세서를 탑재한 대부분의 Unix 및 Unix와 유사한 시스템에서 이것은 오늘날 사소한 것으로 보일 수 있지만, 당시에는 약 100개의 사용자 계정을 가진 단일 MIPS 시스템에 새로운 접근법이 필요했습니다.

1977년 8월호 ACM Communications of the ACM, W. R. Franta와 Kurt Maly는 "시뮬레이션 이벤트 세트를 위한 효율적인 데이터 구조"라는 제목의 기사를 발표하면서 "일반적으로 사용되는 단순 링크 리스트 알거보다 뛰어난 성능"을 입증한 이산 이벤트 구동 시뮬레이션 시스템의 이벤트 큐 데이터 구조를 설명했다.ihms"는 큐 내의 이벤트 수이며, 비표준 시간 분포에서의 양호한 동작 및 최악의 경우 입니다 ) { \ left \ { } \ 。n은 큐 내의 이벤트 수입니다.

Purdue 대학원생인 Robert Brown은 이 기사를 검토하면서 크론과 이산 이벤트 시뮬레이터 간의 유사성을 인식하고 실험을 위한 Franta-Maly 이벤트 목록 관리자(ELM)의 구현을 만들었다.개별 이벤트 시뮬레이터는 가상 시간에 실행되며 이벤트 큐에서 이벤트를 가능한 한 빨리 제거하고 "지금"이라는 개념을 다음 이벤트의 예약된 시간으로 발전시킵니다.이벤트 시뮬레이터를 가상 시간이 아닌 "실시간"으로 실행하면 대부분의 시간을 sleep 상태로 보내고 예약된 시간이 이벤트 목록의 선두에서 수행되기를 기다리는 cron 버전이 생성되었습니다.

그 다음 학년, 컴퓨터 사이언스부의 시스템 스탭에 입사한 Keith Williamson을 포함해, 퍼듀 대학의 대학원 프로그램에 신입생을 채용했습니다."워밍업 작업"으로 브라운은 그에게 시제품 크론을 프로덕션 서비스로 구체화해 달라고 요청했고, 이 다중 사용자 크론은 1979년 말 퍼듀에서 사용되기 시작했다.이 버전의 cron이 완전히 대체되었습니다./etc/cron32/V로 동작하고 있는 컴퓨터 사이언스 부서의 VAX 11/780에서 사용되고 있습니다.

이 cron에서 사용되는 알고리즘은 다음과 같습니다.

  1. 기동시에, 다음의 파일을 검색합니다..crontab모든 계정 소유자의 홈 디렉토리에 있습니다.
  2. 발견된 각 crontab 파일에 대해 다음에 각 명령을 실행해야 하는 시간을 결정합니다.
  3. 이러한 명령어는 대응하는 시간과 "5 필드" 시간 지정자와 함께 Franta-Maly 이벤트목록에 배치합니다.
  4. 메인 루프 입력:
    1. 큐의 선두에 있는 작업 엔트리를 검사하여 향후 실행해야 할 작업 엔트리를 계산합니다.
    2. 그 시간 동안 주무세요.
    3. 각성 시 및 정확한 시간 확인 후 큐를 작성한 사용자의 권한으로 큐의 선두(백그라운드)에서 작업을 수행합니다.
    4. 나중에 이 명령을 실행할 시간을 결정하고 해당 시간 값으로 이벤트 목록에 다시 배치합니다.

또한 데몬은 SAHUP 신호에 응답하여 변경된 crontab 파일을 다시 스캔하고 변경된 crontab 파일을 찾기 위해 1시간 30분에 특별한 "웨이크업 이벤트"를 스케줄링합니다.여기서는 컴퓨터 시간 추적, Unix 알람 스케줄링, 명시적인 시간 변경 및 프로세스 관리에 대한 자세한 내용은 생략하고 있습니다.이 모든 것이 이 cron의 코드 행의 대부분을 차지하고 있습니다.또한 이 cron은 stdoutstderr의 출력을 캡처하여 모든 출력을 crontab 소유자에게 이메일로 보냈습니다.

이 cron에 의해 소비되는 리소스는 주어진 작업량에 따라 확장되며 정기적으로 변경을 확인하는 것을 제외하고 시간이 지남에 따라 본질적으로 증가하지는 않습니다.

윌리엄슨은 공부를 마치고 컴퓨터 사이언스 석사학위를 받고 대학을 나와 뉴저지 머레이힐에 있는 AT&T 벨 연구소에 입사해 이 크론을 데리고 갔다.Bell Labs에서 그와 다른 사람들은 Unix 명령어를 cron에 통합하고 crontab 파일을 사용자의 홈디렉토리(호스트 고유의 것이 아님)에서 공통 호스트 고유의 spool 디렉토리로 이동시켰으며 필요에 따라 crontab 파일을 추가했습니다.crontab명령어를 사용하여 사용자가 crontab을 해당 spool 디렉토리에 복사할 수 있습니다.

이 버전의 cron은 나중에 Unix System V와 BSD 및 그 파생 모델, Sun Microsystems의 Solaris, Silicon GraphicsIRIX, Hewlett-PackardHP-UX IBM의 AIX에서 거의 변경되지 않은 상태로 나타났습니다.엄밀히 말하면, 이러한 구현의 원래 라이센스는 작업에 자금을 댄 Purdue Research Foundation에 있어야 하지만, 이러한 문제에 대한 관심이 거의 없었던 시기에 이루어졌다.

최신 버전

GNU Project와 Linux의 등장으로 새로운 crons가 등장했습니다.이 중 가장 일반적인 것은 1987년에 Paul Vixie에 의해 코드화된 Vixie cron입니다.Vixie cron 버전 3은 1993년 말에 출시되었습니다.버전 4.1은 ISC Cron으로 이름이 변경되어 2004년1월에 출시되었습니다.버전 3은 몇 가지 사소한 버그 수정과 함께 Linux 및 BSD의 대부분의 배포에서 사용됩니다.

2007년에 Red Hat은 vixie-cron 4.1을 cronie 프로젝트에 분기시켰고 2009년에는 anacron 2.3을 포함시켰다.

기타 일반적인 구현으로는 anacron과 dcron이 있습니다.단, anacron은 독립된 cron 프로그램이 아닙니다.dcron은 Dragon Fly BSD창업자 Matt Dillon에 의해 만들어졌으며,[14] 2010년에 Jim Pryor에 의해 유지보수권이 인수되었다.

2003년 Dale Mellor는 Vixie cron과의 상호 호환성을 제공하는 동시에 계산 및 작업 정의 스케줄링에 임의의 스킴 코드를 사용할 수 있는 뛰어난 유연성을 제공하는 Guile로 작성된 크론 변형 mcron을 발표했습니다.[15]일반적으로 mcron 데몬과 crontab 파일은 모두 스킴으로 작성되기 때문에(mcron은 기존의 Vixie crontab도 받아들이지만), 사용자의 작업 큐의 누적 상태는 작업 코드로 사용할 수 있으며, 다른 작업의 결과가 특정 기준을 충족하면 실행되도록 스케줄링될 수 있습니다.Mcron은 기본적으로 Guix 패키지 매니저 아래에 배치됩니다.이 매니저에는 패키지 매니저가 mcron crontab을 일원적으로 내보내면서 작업 실행에 필요한 패키지가 설치되고 대응하는 crontab이 올바르게 [16]참조되도록 하는 프로비저닝(서비스)이 포함되어 있습니다.

webcron 솔루션은 웹 호스팅 환경에서 cron 구현을 사용할 수 없는 경우 링 작업을 정기적으로 실행하도록 스케줄링합니다.

CRON 식

CRON 표현식은 공백으로[17] 구분된5개 또는 6개의 필드로 이루어진 문자열로, 이는 일련의 시간을 나타냅니다.일반적으로 일부 루틴을 실행하기 위한 일정으로 사용됩니다.

코멘트는 코멘트 마크 #로 시작되며, 코멘트는 그 자체로 행에 존재해야 합니다.

들판 필수의 허용되는 값 사용할 수 있는 특수 문자 언급
회의록 네. 0–59 * , -
몇시간. 네. 0–23 * , -
요일 네. 1–31 * , - ? L W ? L W일부 구현에서만
네. 1 ~ 12 또는 JAN ~ DEC * , -
요일 네. 0 ~ 6 또는 SUN – SAT * , - ? L # ? L #일부 구현에서만
연도 아니요. 1970–2099 * , - 이 필드는 표준/기본 구현에서는 지원되지 않습니다.

월 및 주중 약어는 대소문자를 구분하지 않습니다.

특정 시스템 crontab 파일(/etc/crontab)의 경우 사용자 필드명령어 앞에 삽입됩니다.일반적으로 'root'로 설정됩니다.

CRON 형식의 일부 사용에서는 패턴의 선두에 seconds 필드가 있습니다.이 경우 CRON 식은 6개 또는7개의 [18]필드로 이루어진 문자열입니다.

콤마(,)
쉼표는 목록의 항목을 구분하는 데 사용됩니다.예를 들어, 다섯 번째 필드(요일)에 "MON, WED, FRI"를 사용하면 월요일, 수요일 및 금요일을 의미합니다.
대시(-)
대시는 범위를 정의합니다.예를 들어 2000-2010은 2000~2010년 사이에 매년 있음을 나타냅니다.
비율(%)%)
명령어의 퍼센트 기호(%)는 백슬래시(\)로 이스케이프되지 않는 한 줄 바꿈 문자로 변경되며 첫 번째 % 이후의 모든 데이터는 표준 [19]입력으로 명령어로 전송됩니다.

비표준 문자

다음은 Quartz Java 스케줄러와 같은 일부 cron 구현에만 존재하는 비표준 문자입니다.

L
'L'은 '마지막'을 뜻한다.day-of-week 필드에서 사용하면 "마지막 금요일"과 같은 구성을 지정할 수 있습니다.(5L") (지정된 달의 5L")day-of-month 필드에는 월의 마지막 날을 지정합니다.
W
날짜 필드에는 'W' 문자를 사용할 수 있습니다.이 문자는 지정된 요일에 가장 가까운 평일(월~금)을 지정하기 위해 사용됩니다.예를 들어 day-of-month 필드의 값으로 "15W"를 지정하면 "15일에 가장 가까운 평일"이 됩니다.따라서 15일이 토요일인 경우 트리거는 14일 금요일에 실행됩니다.15일이 일요일인 경우 트리거는 16일 월요일에 실행됩니다.15일이 화요일이면 15일 화요일에 발사됩니다.단, day-of-month 값으로 "1W"가 지정되어 있고, 첫 번째가 토요일인 경우 트리거는 월의 경계를 넘어 '점프'되지 않기 때문에 3일 월요일에 실행됩니다.'W' 문자는 요일이 범위 또는 일 목록이 아닌 단일 날짜인 경우에만 지정할 수 있습니다.
해시(#)
요일 필드에 '#'을 사용할 수 있으며 뒤에 1에서 5 사이의 숫자를 입력해야 합니다.특정 [20]달의 "두 번째 금요일"과 같은 구성을 지정할 수 있습니다.예를 들어 요일 필드에 "5#3"을 입력하면 매월 세 번째 금요일에 해당합니다.
물음표(?)
일부 구현에서는 요일 또는 요일 중 하나를 공백으로 두기 위해 "*" 대신 사용됩니다.다른 cron 실장에서는 cron 데몬의 기동시간으로 "?"를 대체하기 위해? ? * * * *갱신할 예정25 8 * * * *cron이 오전 8시 25분에 시작되어 [21]다시 시작될 때까지 매일 이 시간에 실행됩니다.
슬래시(/)
vixie-cron에서는 슬래시를 범위와 결합하여 스텝 [9]값을 지정할 수 있습니다.예를 들어, minutes 필드의 */5는 5분마다를 나타냅니다(주파수에 대해서는 아래의 참고 참조).이것은 보다 상세한 POSIX 형식 5,10,15,20,25,30,35,40,45,50,55,00 의 약어입니다.POSIX 에서는 슬래시의 용도는 정의되어 있지 않습니다.이러한 근거(BSD 확장에 대한 코멘트)에서는 정의가 System V 형식에 근거하고 있지만 [7]확장의 가능성을 배제하고 있지 않습니다.

일반적으로 주파수는 표현할 수 없습니다.범위를 균등하게 나누는 스텝 값만이 정확한 주파수를 나타냅니다(분 및 초의 경우, /2, /3, /4, /5, /6, /10, /12, /15, /20 /30은 숫자로 균등하게 나눌 수 있기 때문에, /2, /3,/4,/8/12).필드에서는 다음 분, 초 또는 일까지가 "정지"되기 전에 시간 단위의 끝에 일관되지 않은 "짧은" 기간이 생성됩니다.예를 들어 day 필드에 */5를 입력하면 달과 윤년에 따라 1, 2, 또는 3일 후에 실행되는 경우가 있습니다.이는 cron이 스테이트리스이기 때문입니다(마지막 실행 시간은 기억되지 않으며 카운트되지 않습니다).정확한 주파수 카운트에 필요한 차이: cron은 단순한 패턴 매처입니다).

H
'H'는 Jenkins 연속 적분 시스템에서 "해시" 값이 대체됨을 나타내기 위해 사용됩니다.따라서 '와 같은 고정수 대신20 * * * *매시간 20분 후,H * * * *'는 각 작업에 대해 지정되지 않았지만 불변한 시간에 작업이 매 시간마다 수행됨을 나타냅니다.따라서 모든 작업을 동시에 시작하여 리소스를 [22]놓고 경쟁할 필요 없이 시간이 지남에 따라 작업을 분산할 수 있습니다.

「 」를 참조해 주세요.

메모

  1. ^ 이것은 배포 유형에 따라 다릅니다.

레퍼런스

  1. ^ "Automation with Cron job on Centos 8". April 6, 2020.
  2. ^ "Difference between cron, crontab, and cronjob?". Stack Overflow.
  3. ^ "Cron Job: a Comprehensive Guide for Beginners 2020". May 24, 2019.
  4. ^ "Crontab – Quick Reference". Admin's Choice. December 21, 2009.
  5. ^ "Newbie Introduction to cron". Unixgeeks.org. Retrieved 2013-11-06.
  6. ^ "Linux - cron and crontab".
  7. ^ a b "crontab", The Open Group Base Specifications Issue 7 — IEEE Std 1003.1, 2013 Edition, The Open Group, 2013, retrieved May 18, 2015
  8. ^ "Schedule Expressions for Rules". Amazon.
  9. ^ a b "FreeBSD File Formats Manual for CRONTAB(5)". The FreeBSD Project.
  10. ^ "#77563 - cron: crontab(5) lies, '@reboot' is whenever cron restarts, not the system". Debian bug tracking system. Retrieved 2013-11-06.
  11. ^ "crontab(5): tables for driving cron - Linux man page". Linux.die.net. Retrieved 2013-11-06.
  12. ^ Minnie's Home Page http://minnie.tuhs.org/cgi-bin/utree.pl?file=V7/etc/rc. Retrieved 2020-09-12. {{cite web}}:누락 또는 비어 있음 title=(도움말)
  13. ^ Minnie's Home Page http://minnie.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/cmd/cron.c. Retrieved 2020-09-12. {{cite web}}:누락 또는 비어 있음 title=(도움말)
  14. ^ Pryor, Jim (2010-01-05). "Cron". arch-general@archlinux.org (Mailing list). Retrieved 2013-11-06.
  15. ^ Mellor, Dale (2003-06-01). "Mcron - User Requirements and Analysis". Retrieved 2019-06-11.
  16. ^ "GNU Guix Reference Manual: 8.8.2 Scheduled Job Execution". GNU Guix. 2019-05-19. Retrieved 2019-06-11.
  17. ^ "Ubuntu Cron Howto". Help.ubuntu.com. 2013-05-04. Retrieved 2013-11-06.
  18. ^ "CronTrigger Tutorial". Quartz Scheduler Website. Archived from the original on 25 October 2011. Retrieved 24 October 2011.
  19. ^ "mcron crontab reference". Gnu.org. Retrieved 2013-11-06.
  20. ^ "Oracle® Role Manager Integration Guide". Docs.oracle.com. Retrieved 2013-11-06.
  21. ^ "Cron format". nnBackup. Retrieved 2014-05-27.
  22. ^ "Timer Trigger Syntax". jenkins.com. Retrieved 2018-02-16.

외부 링크