找回密码
 注册
关于网站域名变更的通知
查看: 258|回复: 1
打印 上一主题 下一主题

守护进程使用syslog函数打印信息(基于ARM-Linux)

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2020-6-3 14:43 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
本文将描述在使用inetd守护进程时,如何通过syslog函数打印消息到日志文件。( _, D# U+ P) E8 l2 j. \
0 ?$ X. ]4 @4 L* f% R
为什么需要这样做呢?根据《UNIX网络编程 卷1:套接字联网API》一书第13章的描述:由于守护进程没有控制终端,它们不能把消fprintf到stderr上。: e  P) ^2 K8 _

$ E+ B" k+ w$ h% l- J4 ^从守护进程中登记消息的常用技巧就是调用syslog函数。2 `4 D/ C1 Y7 v5 U* N3 ?4 C  |$ p9 \

! Z  x9 B6 J/ j6 [% M" T' Z而sysolog函数需要syslogd服务的支持。因此在编译busybox时需要使能syslogd。0 |7 q3 `6 g. q; J4 j# b
: _; ^  c' v5 ~; y, V* }) L, F/ X) C

1 U, D; N+ b( g4 s2 o5 P# G1 a0 }: b2 v( w0 _4 P

. e0 x* E8 O! {% S' Q0 z
8 G. B3 P3 P4 d2 A) l5 E# K0 O# aLinux系统启动后,需要打开syslogd服务。先来看看syslogd的命令选项:
" x& a" ^6 D/ @5 D1 v- V& e( V+ h
[root@BGM /]#syslogd -h8 |( O, v2 ?) }* g) v5 ]
syslogd: invalid option -- 'h'! @4 E. [! x8 ]9 d2 Z8 V1 p; a
BusyBox v1.16.0 (2013-04-15 16:07:27 CST) multi-call binary.
& ~7 c/ |3 L$ w8 O" V" \/ `% i0 t; s# I0 u6 E) @
Usage: syslogd [OPTIONS]
8 q# r" U+ m9 N+ _) g4 `* Q1 A. K: r, S8 Z% L  m1 A
System logging utility.' u9 Y5 P0 S/ W& p3 {' J& W
Note that this version of syslogd ignores /etc/syslog.conf.
+ Q3 G& ~' H0 H" Q# {5 }& e: I" I& r/ w$ Z) y7 R
Options:. B! t1 i" X3 _- G
        -n              Run in foreground1 v* l; q$ N+ g( B
        -O FILE         Log to given file (default:/var/log/messages)1 A# E6 Q. q, _0 I% ^+ X' U
        -l n            Set local log level& i1 L/ p6 ]/ E$ h2 i3 Z
        -S              Smaller logging output
" W# U5 g; |0 o2 g        -s SIZE         Max size (KB) before rotate (default:200KB, 0=off)
" Q# ^) r% N  R0 X7 B0 V        -b N            N rotated logs to keep (default:1, max=99, 0=purge)
( T7 m; A* {1 \) w! Q        -R HOST[: PORT]  Log to IP or hostname on PORT (default PORT=514/UDP)* l  t4 I1 F) X0 t  w2 Z1 a
        -L              Log locally and via network (default is network only if -R)
- P" \; P) c+ U% ?8 m$ N+ l  V        -D              Drop duplicates
, h( g- E% A4 `6 z: J( g        -C[size(KiB)]   Log to shared mem buffer (read it using logread)
8 Y3 p$ X; j+ i7 ?) r
* T+ `, `- E+ J2 C* T0 ^这里我们注意到该syslogd不支持/etc/syslog.conf文件。7 Y. z7 N7 P2 U; _8 i
' J4 q1 C# Z+ e9 Z/ J3 V" y
我们需要使用-L选项,让消息输出到本地(locally),其次其默认的本地输出文件为/var/log/message,
- l- L. r* t/ B* f
% L1 h4 m$ D5 R! r9 j4 z: I如果要修改输出文件,则使用-O选项。
' G0 q$ [% Y0 T/ s" d6 ~! h% c$ k! \! O% ]( l6 y
因此,我这里使用的syslogd命令如下:/ f* B/ r# K" S6 T; ~* k( `* s

, K6 R# r! k. [/sbin/syslogd -L
5 L. C- u- u8 }6 j. }; J! h+ m$ }8 J; F$ H
这里建议将该命令添加到系统的启动脚本中。4 \2 f# `3 w2 k4 j+ k: y4 z

) [0 |* k9 a: D- o8 F) |为了测试函数需要编写一个简单的TCP服务器程序和相应的客户程序,参照《UNIX网络编程 卷1:套接字联网API》的13.6小结编写测试用例,
" `0 o4 H! @% m4 E+ G3 _7 P% {# E% ^9 z9 _) K, P% F
程序如下:
4 c% P4 R$ ]2 ?. Q+ F  h0 e2 c% B" ]. Z
服务器程序:
( D6 c$ v/ j" B% l* j! q/ [& i+ M6 ?- F1 m$ z$ V  I9 H
int main(void)
, F* ^& ~) w/ O. S, q{* K& M. W1 a5 n6 R  F; M$ ~
        socklen_t len;
+ R8 e7 |1 i4 @+ r        struct sockaddr *cliaddr;$ A- O8 ]+ E7 s8 }" n2 X: ]
        char buf[MAX_TCPSERV_BUF];& a+ W* U" i* `2 |/ ]) x- u

- E, D1 N5 ]9 W, Y" c* x        int ret, tmp;
6 {0 m. x9 s- |$ W! q2 x
6 ~  g* g: |/ n: a. E# r' y        openlog("bgmtcpserv", LOG_PID, 0);
" ]  Q/ J# q( o' {3 }
# j3 `6 W$ A) E2 Z6 n        dc = malloc(sizeof(struct data_content));
+ l7 o% k$ F$ H7 w7 J. [3 Q        if(!dc){9 O: h+ I: B0 j, Z2 i2 y
                perror("Unable to malloc data_content ");
* i/ \) w! o; \                exit -1;% J  ^- \8 D! \" [
        }
9 Y" Q9 q$ _/ C
! M" {/ z% p. l; O        cliaddr = malloc(sizeof(struct sockaddr_storage));
0 G4 P  e) I0 f; V6 B        if(!cliaddr){
0 F2 d  K$ K* X                perror("Unable to malloc sockaddr_storage ");
2 U8 C# _4 }6 [6 d* E                exit -1;5 a; c6 X4 I1 g1 C6 l9 t
        }! d* D  g5 C' s# Z7 z9 g
1 l2 k% M  A+ A3 \: d
        len = sizeof(struct sockaddr_storage);7 p2 D8 s9 q& ]0 P( f
        if (getpeername(0, cliaddr, &len) == -1){3 ^$ Q* `7 \- d
                perror("Getpeername error ");
0 V) Y; H% X0 ~                exit -1;
3 ~" N4 z1 J: E1 R, f: d        }
) D7 r4 [) P8 a8 ^9 f0 C. Z3 Z        
8 n( ~0 l  d4 z: }5 r        syslog(LOG_USER|LOG_ALERT, "Connecting from %s\n", Sock_ntop(cliaddr,len));6 S- [. D. S! V6 [
        " X- q. D7 C' g3 k5 Z# x- }
        close(0);
1 f9 F  L- p) ?        closelog();4 m/ E+ e  E% n; W+ r% J( d- F
        exit(0);
3 x7 v- K, Q3 O# O6 a) U/ w, f}8 i% [; y9 V' t3 Y
/* include sock_ntop */
9 c& p4 ^1 j' G/ W! i/ n" ?7 schar *( x: p5 e/ B3 X/ U3 W/ k" u6 W
sock_ntop(const struct sockaddr *sa, socklen_t salen)9 Q( t5 k* f$ t& c! i+ n
{
8 \* V" g& x) `- Q! ~6 z! D/ {    char        portstr[8];
/ a+ M' L. A# ~    static char str[128];        /* Unix domain is largest */0 y4 }: k; v) M0 ?7 u- c; r) X
/ M' n9 X5 O9 d4 M6 x; U
    switch (sa->sa_family) {4 D4 i  ?" M/ f# B/ C8 w
    case AF_INET: {
# p" D3 l& P% j& l0 s) q7 M        struct sockaddr_in    *sin = (struct sockaddr_in *) sa;$ H# g& k$ W+ H( u# W
, q; [+ y; T0 V. l
        if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == NULL)( x+ v/ A8 s1 o* ]
            return(NULL);
! q7 `7 @+ ~. L        if (ntohs(sin->sin_port) != 0) {
. ~  y) D; H3 v! ~5 C; h            snprintf(portstr, sizeof(portstr), ":%d", ntohs(sin->sin_port));
) I5 |3 g$ T/ x" _; \$ o            strcat(str, portstr);3 V& Q( _' X* J7 a: o2 d
        }* N: q6 u3 W9 r' d6 }0 f5 C! Q
        return(str);
! z6 X. o. n$ B1 \7 B+ `    }
- B4 e0 [$ X- O/* end sock_ntop */
& P6 p5 B, ^9 g) ~7 l! s0 h
- n7 P( _4 B3 u1 r( P% Q# A0 r#ifdef    IPV6! W) I7 O7 m: ?4 w
    case AF_INET6: {2 A# H- F1 ?5 T. N+ Z) ]
        struct sockaddr_in6    *sin6 = (struct sockaddr_in6 *) sa;
3 b1 Q8 n  c+ G# J5 X% |9 [. k" N3 \: k* T/ A
        str[0] = '[';
& A3 J9 X# H+ v) P        if (inet_ntop(AF_INET6, &sin6->sin6_addr, str + 1, sizeof(str) - 1) == NULL)
9 \* b+ Z* x4 m# X            return(NULL);
9 Q* e+ p: d' |5 p        if (ntohs(sin6->sin6_port) != 0) {
7 f9 F# A2 Q6 O8 P            snprintf(portstr, sizeof(portstr), "]:%d", ntohs(sin6->sin6_port));
7 U/ V# `$ H" B) f) d7 k            strcat(str, portstr);
! Y7 a4 \8 y! ?+ @. \! |0 p            return(str);
5 @7 M% ]4 {3 L5 P- p        }
, M  m9 b# j2 h# Z  D* H+ R5 R5 m        return (str + 1);! L& p) ?9 V+ d  ?" b. H$ u8 T9 Z, N8 d
    }
  W3 f' b0 m6 B; l#endif6 T+ J& V3 X0 _4 \0 T, ^  t
/*
1 G" i0 M) L% w6 Y#ifdef    AF_UNIX8 M6 s4 V  y1 E$ \
    case AF_UNIX: {) ~3 H* |' ?! H7 K
        struct sockaddr_un    *unp = (struct sockaddr_un *) sa;
, W* g  \: t( S- w; ^4 H             OK to have no pathname bound to the socket: happens on# Z% t- h) z6 t2 e4 A6 r8 W: w
               every connect() unless client calls bind() first. ! X* ]' p2 |* w2 k: u; f1 m! `
        if (unp->sun_path[0] == 0)
/ _! b" _- ?1 a" L" w; V% H            strcpy(str, "(no pathname bound)");8 y9 T' N. [+ E! ~2 h8 P' b
        else  W4 L: u$ e2 _1 P3 V2 G+ x
            snprintf(str, sizeof(str), "%s", unp->sun_path);
; b8 @& @, a, w/ J        return(str);
6 ~/ q' g+ t6 Z9 z! M5 [    }
" r4 B/ X; ~( [0 B* F#endif*/9 ?4 X0 @+ `- b1 r

' u/ }& r7 N" l9 v1 p8 X// #ifdef    HAVE_SOCKADDR_DL_STRUCT9 Q+ I. {7 t& M$ O8 y9 C) e
//     case AF_LINK: {
. M' @/ e9 z2 a' X0 [# ]//         struct sockaddr_dl    *sdl = (struct sockaddr_dl *) sa;
1 D! J1 e. G4 s4 v" \# j  ~4 R% |: I7 g
//         if (sdl->sdl_nlen > 0): L9 b/ P* u4 O8 ~% W) G. L
//             snprintf(str, sizeof(str), "%*s (index %d)",+ b- ?/ H' @; e7 y+ t3 E
//                      sdl->sdl_nlen, &sdl->sdl_data[0], sdl->sdl_index);
: R: ]) f! M: I1 z5 K0 B" w! D//         else
: W( {" @+ n5 e* C0 m7 x//             snprintf(str, sizeof(str), "AF_LINK, index=%d", sdl->sdl_index);
+ `3 R' e5 I6 S* e; _//         return(str);. T! r0 g  {9 u* u
//     }) G) d  q. ~3 j4 ~4 Q/ g! \: A
// #endif0 i' V( d3 w. {6 G+ K
    default:: @1 ?" }/ \5 i* f) G
        snprintf(str, sizeof(str), "sock_ntop: unknown AF_xxx: %d, len %d",
: B" E3 Y6 w# B5 r; g                 sa->sa_family, salen);0 o% \5 ?+ f5 E  e! H$ w! D. R4 {
        return(str);
' W9 s1 f+ _/ d' U1 t, a4 j. W    }
( G5 r2 H0 W; W* V    return (NULL);+ J0 ]9 N' v) ?' }0 e3 v1 G
}$ Y# h+ p1 P2 Z& }
& T+ ]3 A/ a0 H6 Q5 B# P$ x1 e( B  w: C" |
char *6 ]1 f; \  z- A  d) m# l) z% t
Sock_ntop(const struct sockaddr *sa, socklen_t salen)
* O4 P0 A) n! T{& c! x1 K8 W' W3 i7 w. f6 Y1 V' A5 L
    char    *ptr;
' ?. c1 ~# t* o6 j3 F8 ]1 ^& D7 o7 y0 G' T. P( s2 _+ x
    if ( (ptr = sock_ntop(sa, salen)) == NULL)3 R; Y* h! F! r$ U4 u
        perror("sock_ntop error");    /* inet_ntop() sets errno */
( }3 e" _, h. d1 V" y: V) ]6 `    return(ptr);
5 z" K; x1 h1 H' F1 @  t2 _4 x- T}
4 R; M* S8 _  ~! s' _- J* k
* u, _& \9 L  r0 A( j% y客户端程序:
) [  e* @% l! ]0 H' |  Y5 P#define SERV_PORT 30001& r% g! ^# ?% [' @8 }+ z" W% q
#define SERVIPADDR "192.168.0.200"/ z4 b( a& }- A3 p  S6 Y' n: s  }9 d6 N7 L

# o: E  G9 n; |" |, ]* z/ L$ ^3 Zssize_t                                                /* Read "n" bytes from a descriptor. */
) e8 w& x1 r$ Qreadn(int fd, void *vptr, size_t n)
+ T/ v0 ~2 I8 W- f{' g  `6 _8 m7 A
        size_t        nleft;
$ L* ^$ I6 e, i  j# {! b        ssize_t        nread;: [) V' O: j) e% C) e
        char        *ptr;: Q$ n2 l  I; t9 r) Q9 W- c" [  |0 Q8 U

  }- S) s; P% {9 v; `" Z/ X        ptr = vptr;
3 O3 S; w" Z! U: Y) c        nleft = n;; Z1 a1 k1 Z$ `$ P' l0 R
        while (nleft > 0) {7 u9 K7 C# G2 _, g- Q, F! U& ?
                if ( (nread = read(fd, ptr, nleft)) < 0) {
& |5 h! d$ A. Y: `0 M) V                        if (errno == EINTR). t# N4 `# B- K/ a; t
                                nread = 0;                /* and call read() again */2 i  Q8 m6 z7 B6 a( a: o, i
                        else
# s" [; _+ X; C0 {                                return(-1);4 A) `  K* A7 B% u& A* H& f9 ]
                } else if (nread == 0)
) n1 Y5 @2 y8 g* t) n6 P' P                        break;                                /* EOF */; \. V* U4 `) {6 `+ I$ s. @) k
: u4 B+ q9 e' A- g
                nleft -= nread;# h. N. ]5 d, i6 R6 ]$ Q- N! p
                ptr   += nread;
* {- l, F3 k0 v: F6 i/ {9 c        }
) V% {$ a, w7 E+ Q, I+ j6 p+ m        return(n - nleft);                /* return >= 0 */% A2 }' q* \- z( E/ u
}
% P& [$ x( J5 C- V( q9 U- T, ~$ `; Z" A9 e; s" D6 G
int main(void)
1 M/ D1 R! v/ f6 p0 U0 O! S5 ~{
2 S, ~' G4 D' u0 T; N: y% E        int sockfd, ret;
& v9 n4 V! x! D2 I0 L% Y4 @        struct sockaddr_in  servaddr;/ j/ `2 _, f4 N  L) S
        int n;  Q$ ^( T7 A- m1 H3 ?) L  q' p0 T
        char buf[512] ;
" a: P. S. B* v; N        1 J! h  v) M/ H0 a% b" b
        sockfd = socket(AF_INET, SOCK_STREAM, 0);" W  r1 ^4 r% W- u" L' ]
        if(sockfd < 0){" c# T5 M. o2 g% q' [2 }" y+ \
                perror("Socket error");9 i0 W9 I, L% B- u6 U* \" V; O
                return -1;
3 x7 o& h1 F7 H* c, _        }
: F. X0 Y7 Q% b) d* w3 n2 r$ R        & i& @* q6 E7 t5 e
        memset(&servaddr, 0, sizeof(struct sockaddr_in));
# a2 V# b* H4 A; L2 b4 ~! V; z8 f        //bzero(&servaddr, sizeof(servaddr));+ |5 W) `# |* T$ d4 E5 L
        servaddr.sin_family = AF_INET;
' P7 X. ?! |1 ~  E        servaddr.sin_port = htons(SERV_PORT);& I4 R2 b- o3 F5 o* p4 r5 s- S% }
        ret = inet_pton(AF_INET, SERVIPADDR, &servaddr.sin_addr);" E- r9 g5 R. M$ Q
        if(ret < 1){
$ y, v' v& W) d- i# C) ^# B  i                perror("Inet_pton error");: g9 m  J6 ^) b
                return -1;4 Z. L; \3 n7 l# E8 U
        }, C  E. T, H6 E% p

5 A9 y% v, i* [5 N' d' l$ G0 l0 F* ]        ret = connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
( ]6 x: v% ?: t$ a3 D6 j* D        if(ret < 0){5 F: z2 E: I" w& F
                perror("Connect error");+ @% ]! \; P+ ?# e4 y
                return -1;, ]0 \! X: U6 q
        }; t+ r) q( y0 `5 N+ ]! y; h
* H7 @4 f- a& @7 b
        close(sockfd);, A2 X3 Z! U& C3 H# @9 L
}( {9 Y1 H0 o& H% z, _# Q
服务器程序编写完以后,为了让inetd能够调用我们的服务器程序,需要修改配置文件。
+ x* M' [2 x: R5 R  Z
! }: a2 U; R* q# I7 y# h' S. I) U首先,修改/etc/services,增加如下:- E8 S/ |# t  A$ [3 x
: K! z" Q8 D  R% }0 l# k: R0 o/ \
mytcpser        30001/tcp                        # Used by BGM
& v$ Y; q2 A" {+ U) U7 U3 w$ l/ {
' }. g2 n; \/ D- W6 n1 L其次,修改/etc/inetd.conf,增加如下:
7 l$ z, A4 c& u
2 i2 \2 q- N: y7 Nmytcpser stream tcp nowait root /home/bgm/bgmtcpser bgmtcpser
( h( N/ o1 |6 `: P: {9 w
% L) K$ k( @" ], L' [这里的mytcpser需要和services文件中的第一个字段相同,其次/home/bgm/bgmtcpser为服务器程序所在的路径。
& ^6 U1 b# ]: d( w1 U3 k7 p, f# }/ z1 N# x, [% b3 y" r& P2 F- z
修改完配置文件后,将服务器程序bgmtcpser复制到/home/bgm目录下。8 U: u+ ~2 ^. D) Z, \

& O, y$ @1 W4 f% v9 k# l" Z; `使用netstat 来查看是否inetd已经创建端口号为30001的监听套接字:
; _( y7 I2 G' S7 n# T7 I
+ A! r# o+ N  z, `[root@BGM /]#netstat -an | grep 30001
& r0 e! r! |/ O3 X6 Q" B; s$ y$ T3 |
tcp        0      0 0.0.0.0:30001           0.0.0.0:*               LISTEN   
8 A1 R* N) E  P7 Z; a( s
8 t/ u4 I4 u( b然后我们执行客户程序cli,执行完以后我们查看/var/log/messages中的内容:
8 o2 m5 Q) P) t( N. y# hJul 23 13:13:42 BGM user.alert bgmtcpserv[2587]: Connecting from 192.168.0.200:40571
2 {0 J, Y" U  F. R) \7 r3 e! r' G' h* D4 i7 D0 [/ o1 Z
这里的"Connecting from。。。"正是由syslog函数打印的。1 @" i! K- U. O0 [  {7 [
- k: }7 B1 M/ {9 {

2 f- {5 @4 J  g* n7 X$ ^9 C7 O
9 E( Q5 ?8 Y( t) w# X2 y% w+ r, K1 d, l# t' J( G% u

( Q6 G5 ]* ]/ R5 _7 y  t% Y& `+ A  D2 K8 `: \
3 W9 f( v  ]6 U- V2 q& A

该用户从未签到

2#
发表于 2020-6-3 15:30 | 只看该作者
基于ARM-Linux
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-11-25 21:36 , Processed in 0.187500 second(s), 27 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表