ntp 클라이언트에서 서버 접속 관리 (select, alarm 등)

dorado2의 이미지


임베디드 환경에 사용할 ntpclient를 테스트 중입니다.

http://doolittle.icarus.com/ntpclient/ 에서 다운로드 받았고,
컴파일 및 실행은 잘 됩니다.

ntpclient -h time.bora.net -d -s -i 15 &

위 명령을 수행하면 해당 NTP 서버에 15초마다 접속하여 시스템의 시간을 설정합니다.
현재 임베디드 시스템에 cron 같은 명령이 지원되지 않는 것 같은데 저렇게 백그라운드로 실행하면
내부적으로 15초마다 실행(select의 timeout 이용)되어서 그냥 저렇게 사용할까 합니다.

문제는 유사시의 경우입니다.
1. 특정 NTP 서버가 연결이 안 될 때
2. NTP 서버들의 주소가 변경되어야 할 때.
(여기서 서버 주소 변경은 NTP 서버 리스트 파일을 외부 프로그램이 수정하는 경우를 생각하고 있습니다.)
3. 임베디드 기기의 네트워크 자체가 안 될 때..

1번의 경우에 대비해서는 NTP 서버 리스트 파일(ex. ntp.conf)에 2개 이상의 서버 목록을 두고
첫번째 서버에서 응답이 없는 경우에 두번째 백업서버를 host로 해서 접속하려고 합니다.
(따라서 위 코드에서 -h 옵션은 없애도 되네요.)

alarm()을 이용해서 NTP 서버로부터 몇초간 응답이 없으면, 다른 서버로 ntp 패킷을 보내도록
ntp client 소스 자체를 고쳤고요. 나름 동작하는 것 같습니다.

2번의 경우는 NTP 서버 주소를 바꾸는 것이 외부 프로그램이기 때문에 그 외부 프로그램이
스크립트를 실행해서 killall ntpclient, 하고 ntp.conf 수정하고 다시 system() 함수로
위 명령을 실행하면 어떨까 하는 생각이 드네요.

그런데 마지막 3번의 경우 지금대로라면 NTP 서버와 connection을 연결할 때
error가 나서 프로그램이 종료가 될텐데요. 이를 어떻게 알고 새로 명령을 수행해 줄까 하는 문제가 있네요.

사실 네트워크가 되는데 NTP 서버가 불능에 빠질 경우보다, 기기 자체의 네트워크가 안 되는 상황이
더 빈번할 것 같은데요...

이 경우 스크립트로 (rc.d 아래두게 할..) 어떻게 할지는 감이 안 오는군요.
스크립트만으로 가능한지도 잘 가늠이 안 되어서요.

약간 경험 있으신 분의 힌트 좀 부탁드립니다.

덧/
매 주기마다 NTP 서버에 요청 패킷을 보내는 것이 대충 아래 코드와 같은데요.
이 안쪽에 alarm을 써서 NTP 서버로부터 응답이 없는 경우를 처리하도록 했습니다.(주석부분)
실제 코드는 약간 다르긴 하지만, 우려할만한 side effect는 없을까요?

	fd_set fds;
	struct sockaddr sa_xmit;
	struct timeval to;
 
	to.tv_sec=0;
	to.tv_usec=0;
	for (;;) {
		FD_ZERO(&fds);
		FD_SET(usd,&fds);
		i=select(usd+1,&fds,NULL,NULL,&to);  /* Wait on read or error */
		if ((i!=1)||(!FD_ISSET(usd,&fds))) {
			if (i<0) {
				if (errno != EINTR) perror("select");
				continue;
			}
			if (to.tv_sec == 0) {
				if (probes_sent >= ntpc->probe_count &&
					ntpc->probe_count != 0) break;
				send_packet(usd,ntpc->time_of_send);
				alarm(2)    // 2초후까지 응답 패킷 없으면 EINTR 발생
				++probes_sent;
				to.tv_sec=ntpc->cycle_time;
				to.tv_usec=0;
			}
			continue;
		}
		pack_len=recvfrom(usd,incoming,sizeof_incoming,0,
		                  &sa_xmit,&sa_xmit_len);
 
		alarm(0)    // 패킷 받으면 alarm 셋팅 해제
 
               ........ 후략 .........
dorado2의 이미지


참 ntp 서버 재설정 할 때는...

static void setup_transmit(int usd, char *host, short port, struct ntp_control *ntpc)
{
	printf("connect with %s \n", host);
	struct sockaddr_in sa_dest;
	memset(&sa_dest,0,sizeof sa_dest);
	sa_dest.sin_family=AF_INET;
	stuff_net_addr(&(sa_dest.sin_addr),host);
	memcpy(ntpc->serv_addr,&(sa_dest.sin_addr),4); /* XXX asumes IPv4 */
	sa_dest.sin_port=htons(port);
	if (connect(usd,(struct sockaddr *)&sa_dest,sizeof sa_dest)==-1)
		{perror("connect");exit(1);}
}

와 같은 함수를 이용합니다. 이 때 connect에러가 날 때 어떻게 처리할까가 문제이네요.

bushi의 이미지

inittab 의 respawn 에 등록하세요.
죽으면 재실행됩니다.
서버 리스트파일 수정 뒤 kill 만 하셔도 되겠고요.

다만, 예외상황에 의해 너무 자주 많이 죽으면 콘솔로 보기 싫은 메시지가 출력될 수도 있고,
어쩌면 init 이 강제로 비활성화 시킬 수도 있습니다.

OTL

dorado2의 이미지

respawn에 등록하니 일단 init q로 해보면 실행되는 것은 확인할 수 있었습니다.

1. 해당 프로세스를 kill하고자 하는데 어떻게 해야할까요?

원래 기존 스크립트에서는 killall 이란 명령어를 썼었는데,
killall ntpclient 라고 실행해도 kill할 프로세스가 없다고만 나오네요.
inittab에 두니 ps -aux해도 ntpclient라는 프로세스가 안보이고요.

inittab에서는

ns::respawn:ntpclient -s -i 15

정도로 작성을 했습니다.

2. 언급하신 사항인 것 같은데, 15초마다 시간을 동기화하는 것이 그렇게 빈번한 것인가요?
테스트를 위해 NTP 동기화 최소 시간인 15마다 시간을 받아와서 설정하게 했는데,
/var/log/messages에 Id "ns" respawning too fast: disbled 5 minutes라고 나오네요.

실제 사용시에는 5분, 10분 마다 동기화하려고 합니다만, 궁금하네요

cjh의 이미지

1. ntpclient를 반복 실행하는것보다 ntpd를 돌리시는게 더 낫고

2. 15초는 너무 짧으네요. (5분, 10분도) 하루정도가 나을것 같습니다.
http://en.wikipedia.org/wiki/NTP_vandalism

--
익스펙토 페트로눔

--
익스펙토 페트로눔

dorado2의 이미지


임베디드 기기에서 사용하는데 원래는 ntpd나 ntpdate, ntptime 등의
바이너리가 있어서 사용을 해보기도 했습니다.

그런데 약간 다른 부분에서 유발된 문제가 있어서 ntpclient를 사용을 하게 된 것입니다.
/etc/services 쪽에서 설정된 ntp용 123번 포트를 프로그램에서 못 찾는 문제가 있어서
급히 피해가느라.. (getservbyname() 함수가 제대로 동작 안하는데 이유는 모르겠고, inetd도 잘 안 되고요.)

지금은 테스트 중이라 15초로 해본것이구요, 소스에서 default값이 600초이더군요.
추후에 사용시에는 시간 단위로 설정하게 될 것 같습니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.