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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
本文将描述在使用inetd守护进程时,如何通过syslog函数打印消息到日志文件。
6 j2 B% ]. {& ^& E6 @: A0 S1 k( @& L
为什么需要这样做呢?根据《UNIX网络编程 卷1:套接字联网API》一书第13章的描述:由于守护进程没有控制终端,它们不能把消fprintf到stderr上。
2 |2 s" t" S1 x6 a+ \8 N# T/ t
$ v) \. {, z5 n4 Y/ q& ~- Z4 }从守护进程中登记消息的常用技巧就是调用syslog函数。( R3 L7 i& j4 g0 ?

5 \8 X* K  W# R# G而sysolog函数需要syslogd服务的支持。因此在编译busybox时需要使能syslogd。
4 t3 t  z# D9 k8 ?+ ?) D6 N1 }: x  w, S/ D  h1 {
7 x$ k$ G- K9 J( L

* N& E: Q: w$ `' |6 ~
, O- Y  o3 W4 P* P( L/ _+ B3 q! Z1 O
% |: Q( W/ {( Y2 f0 C0 RLinux系统启动后,需要打开syslogd服务。先来看看syslogd的命令选项:
( p0 Y+ ?8 h& x+ j( X3 O. M
, y& j( M- q2 o% R[root@BGM /]#syslogd -h
0 ]% o. Q* z! b3 w& }! F& fsyslogd: invalid option -- 'h'
" e$ I. H& D5 U) M# S* _BusyBox v1.16.0 (2013-04-15 16:07:27 CST) multi-call binary.
7 l2 `9 g) z; X* f! m! N! |% B- ^/ I4 u, V, s* n
Usage: syslogd [OPTIONS]
" w. y/ s. B, X6 |% e6 E. }# l4 a1 P3 r6 Q1 O$ y+ Q  ~
System logging utility.
# W$ ?/ F- D/ A" l, R4 g- D! [) {Note that this version of syslogd ignores /etc/syslog.conf.  z' F  m  P$ h# q

3 I. E% p  z4 MOptions:8 a; e5 P* l4 [4 \
        -n              Run in foreground. R2 E# F# w: H# ?5 z
        -O FILE         Log to given file (default:/var/log/messages)
% ]5 E( c+ S6 H" \* x4 L( N% d        -l n            Set local log level
" Q  J5 N/ t0 P* Y5 Q. p3 j        -S              Smaller logging output# {; y) z; f5 i
        -s SIZE         Max size (KB) before rotate (default:200KB, 0=off)
- m1 |5 Z% F" Z; u: S' q2 {! I; H        -b N            N rotated logs to keep (default:1, max=99, 0=purge)  [8 j% E- x$ A2 T' R  L# x
        -R HOST[: PORT]  Log to IP or hostname on PORT (default PORT=514/UDP)
5 g) A' }& F. @  Z- N3 r        -L              Log locally and via network (default is network only if -R)
! k8 M6 Q6 i3 W. e        -D              Drop duplicates
& I4 x! u+ z) S5 m  B        -C[size(KiB)]   Log to shared mem buffer (read it using logread)
) S4 G' J/ r% ^: Z. G8 x6 L; G8 ?* [$ k1 f4 v. [! j* j! O% \5 Z2 H
这里我们注意到该syslogd不支持/etc/syslog.conf文件。
5 t, C  Y3 H: ]* A0 H3 E5 E/ H8 s1 H6 R1 L: \
我们需要使用-L选项,让消息输出到本地(locally),其次其默认的本地输出文件为/var/log/message,2 K+ U& j: U# Z& R. @6 J# i$ [$ s
8 C- d2 s& f' _0 o' [" s2 |3 y
如果要修改输出文件,则使用-O选项。
& L$ M( @: d, \& g& n+ j9 f: ]$ |; H# x0 l8 G4 N! O
因此,我这里使用的syslogd命令如下:& x7 q: N7 i0 _  I* i

4 H, H$ ^5 j% v/sbin/syslogd -L
2 V/ T* @) T3 Q# F% h, G8 w$ i2 b; v- q9 O
这里建议将该命令添加到系统的启动脚本中。# B- l8 }3 g) a! _' E$ _& ^" y6 g2 Z
7 d3 w$ d; ]$ c+ b! n
为了测试函数需要编写一个简单的TCP服务器程序和相应的客户程序,参照《UNIX网络编程 卷1:套接字联网API》的13.6小结编写测试用例,# c' y; G& T" C  c

+ S) F1 g& D5 P% C9 e5 l! h程序如下:
( I, F0 W$ m/ y, k, E! S# k) O+ J
- m9 \" ~4 [/ e服务器程序:, J; I5 g. u4 q* b* z" V

& j: b7 X/ [9 X4 n$ l1 hint main(void)
8 J7 e0 L: ]! @: k2 N{; `  V& Z, K& l  k9 `, h; Z7 l/ l
        socklen_t len;
0 }. m5 x3 r5 \8 x( r$ b        struct sockaddr *cliaddr;, ]. H* d2 h8 n3 @1 @% n9 o
        char buf[MAX_TCPSERV_BUF];; M7 E/ G3 x1 T2 {0 q3 K* J
/ i4 E+ Z: C, v# u* T8 ~
        int ret, tmp;
" Q, n2 R8 d$ R  T9 o: {! @
- P' F3 c: P, ]% U# B) ]. @4 N        openlog("bgmtcpserv", LOG_PID, 0);# ?( w+ Y. o6 x3 X
( x9 x% P4 M6 @4 w
        dc = malloc(sizeof(struct data_content));# k! N7 W1 G3 O' p! p. k, y
        if(!dc){9 r4 r7 ^1 [7 h! F
                perror("Unable to malloc data_content ");1 Y. K0 I+ M6 N- c: {% \  b
                exit -1;
1 E; C# e5 ?( e6 d9 F        }
! Y% N# Q$ H- G2 p# d5 P1 m3 n3 m- d. H: w. |7 E7 j: m0 J& x7 b$ S
        cliaddr = malloc(sizeof(struct sockaddr_storage));
8 L& }- Y( z3 Z/ g        if(!cliaddr){
) q! i8 @* F  p) Y                perror("Unable to malloc sockaddr_storage ");1 L/ s! p+ e( Q7 z- s$ K
                exit -1;, u" U7 l; s+ e& ^4 D; \
        }
$ C" \, A- D! m( w) F8 V
# v0 a# ?# j* ?6 v( r1 |: _        len = sizeof(struct sockaddr_storage);, Z, ^, u- |  c- W  C% W/ `
        if (getpeername(0, cliaddr, &len) == -1){/ u  V# H9 P" [7 M% @1 O3 c2 r
                perror("Getpeername error ");, |+ x; V$ E/ V8 A2 |+ ?
                exit -1;, P& p" D' h, M4 ~& Y* M
        }' v. y$ f" F8 d3 ?4 [: k2 i' @
        
, p5 w* g# b3 i' U+ N! K        syslog(LOG_USER|LOG_ALERT, "Connecting from %s\n", Sock_ntop(cliaddr,len));
" E" g* C5 J& A        
( E. [( q' w; k5 z        close(0); ; X& G- R% A% l2 H& S  B
        closelog();
# G8 w9 F- [9 W5 k" u( _  X        exit(0);4 i, r. S) F7 J7 g# o
}# S* H& I" U' I' N/ P# u) a* D; w
/* include sock_ntop */
$ J& d) P# d5 T5 a- z9 \char *
& l' l! W/ }+ Usock_ntop(const struct sockaddr *sa, socklen_t salen)
3 R# ~" e( j' i8 I{6 _* \$ X) p2 y7 G
    char        portstr[8];$ J8 f8 k& b! e0 @
    static char str[128];        /* Unix domain is largest */
5 ?' h: p- x2 L8 S. X( g; ^/ H! L. b" W) |3 y0 U
    switch (sa->sa_family) {
: b. Q( |  Y3 ]# r6 k9 a! F) ~    case AF_INET: {5 ^! M& E  k  R! t/ n5 u# f3 E
        struct sockaddr_in    *sin = (struct sockaddr_in *) sa;
! ?" n% J2 P2 P/ \& H, B+ m6 D! x& b6 u/ S$ H
        if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == NULL)2 e$ y5 y4 z& L2 R! N3 x5 w
            return(NULL);
; {! R2 S7 z( i2 ~) \) E6 y        if (ntohs(sin->sin_port) != 0) {4 B9 C( P3 [5 h' M1 p5 ^
            snprintf(portstr, sizeof(portstr), ":%d", ntohs(sin->sin_port));
5 ?( v* k7 i& }  |5 {# o            strcat(str, portstr);+ E; c/ S  b: h  k9 l, q& R
        }
3 c% b* M  w% w1 K9 O' n        return(str);
5 |" c" g4 Q( R3 ]$ P( a    }1 g; I( i. f1 |! r! X
/* end sock_ntop */
* x% g0 q! q- c- L7 S8 U
- g7 X- ?4 E9 W( ]5 w/ t#ifdef    IPV6
9 s# ?: D, n6 z+ T. j$ A( C/ u    case AF_INET6: {# ]9 Z- Y8 G5 u  n, v/ y
        struct sockaddr_in6    *sin6 = (struct sockaddr_in6 *) sa;( K) Z0 f$ n' V" g: t' ]# S/ t$ r  S

  s  N3 {2 F, b3 T5 Z        str[0] = '[';
  b! Z( a6 J( u  R8 |        if (inet_ntop(AF_INET6, &sin6->sin6_addr, str + 1, sizeof(str) - 1) == NULL)0 Z7 h. B2 L' f; A# n2 Z5 I! U
            return(NULL);' ~: ?4 G/ Z1 A! T7 }2 I9 i
        if (ntohs(sin6->sin6_port) != 0) {4 {% s: x9 i. t5 H3 L% b
            snprintf(portstr, sizeof(portstr), "]:%d", ntohs(sin6->sin6_port));
/ N% y0 Q0 x. @1 S            strcat(str, portstr);' x; D, ~/ u0 u1 R4 c- _- n
            return(str);& c$ t' j. @5 m( ~0 v! U
        }  Y5 m8 O5 l3 X" y3 u( T
        return (str + 1);' u& t- e% A# n. Y8 P* f/ Z
    }2 ?7 O5 Z  a" J8 J! D, i
#endif
0 \% z/ {9 f$ F! ~  F3 z% f) K0 j! g/ E/*$ @. l$ a- ]/ v$ u) y
#ifdef    AF_UNIX
' b! D4 D8 p) v; P    case AF_UNIX: {
- S2 W2 D- a3 l5 u# T        struct sockaddr_un    *unp = (struct sockaddr_un *) sa;- E! j' H# X1 U- R
             OK to have no pathname bound to the socket: happens on3 W. b1 w# _' O! z
               every connect() unless client calls bind() first.
* ^' `5 |8 o# p/ Y        if (unp->sun_path[0] == 0)
) h# u* [8 c# k# I& a! \            strcpy(str, "(no pathname bound)");, {5 u3 x$ M8 r* I; Z
        else$ w) M6 I3 C" p6 n" {7 s9 F
            snprintf(str, sizeof(str), "%s", unp->sun_path);) b; E+ R. Z! L  N
        return(str);
3 I1 P5 Y; {" V+ g/ ~9 {    }0 F) g' i. K2 f" W& B
#endif*/, i8 T: P" ]6 B" x* A! D
& U0 x' `% l2 ^3 D  N( I
// #ifdef    HAVE_SOCKADDR_DL_STRUCT; |/ M8 q* I0 G  D
//     case AF_LINK: {/ k0 O3 P, R. Z
//         struct sockaddr_dl    *sdl = (struct sockaddr_dl *) sa;, a  t- g' ^+ r5 Z3 T
/ i& I& a' |( P" I9 J( h: m. U6 x
//         if (sdl->sdl_nlen > 0)! f4 t7 L# ?' p5 ]2 B
//             snprintf(str, sizeof(str), "%*s (index %d)",; h% `3 n" o) N1 b
//                      sdl->sdl_nlen, &sdl->sdl_data[0], sdl->sdl_index);1 }' `- r& g( q7 [0 a
//         else& E3 [1 s8 r. x8 d3 k: G
//             snprintf(str, sizeof(str), "AF_LINK, index=%d", sdl->sdl_index);8 v, X( h1 _4 I; S2 i  j
//         return(str);
& `; X4 M4 j0 D' H* p* c* k2 ~//     }
1 n7 |6 J& i- D) I6 H// #endif
  e/ H/ R# f# C    default:0 v3 S7 J' X" G2 v
        snprintf(str, sizeof(str), "sock_ntop: unknown AF_xxx: %d, len %d",
4 D+ S/ D/ J& f8 h                 sa->sa_family, salen);: n4 ?; @. F2 Q# L( j: I# G4 ^
        return(str);
; @3 k0 Y& D+ s+ {+ ~9 d3 r! C    }
! K! z! R; g  A% P) B- I6 B: V    return (NULL);& o  B! v+ q" [* s3 ^9 B% i
}1 O, P4 M/ Y: {( O  t( L$ T
8 g# W" t3 o; p9 |1 F8 C) s
char *$ L1 q  D$ C; f
Sock_ntop(const struct sockaddr *sa, socklen_t salen)
1 K( @" Z* `2 l: s{
, x) m6 f; m: p6 C5 a    char    *ptr;5 g; K3 X& b$ p: ~. W
+ d. t- ?/ K+ H% s5 R
    if ( (ptr = sock_ntop(sa, salen)) == NULL)+ u1 C& }$ Y& p1 j* ]
        perror("sock_ntop error");    /* inet_ntop() sets errno */3 h+ o' U% g. x. K# ]. \+ v
    return(ptr);
9 {) d9 R: c" L  j+ G, f3 I}8 y1 D, |1 C. y5 h+ P4 R% u; _

3 E+ l  J8 s# O$ E, [; ~5 u4 c2 _; D客户端程序:
* a. M, C, \* ]! }6 e#define SERV_PORT 30001
  H0 u, h6 c$ L; i#define SERVIPADDR "192.168.0.200"9 Z, k% g8 S' B2 g" |4 z4 {' n1 r
" y- k- W. Z6 q4 v$ s- A  |: a( Z
ssize_t                                                /* Read "n" bytes from a descriptor. */
3 p- Q" ?$ U3 \; _9 s) _readn(int fd, void *vptr, size_t n)
% |' m6 h; C9 d* }* g{
0 @1 w+ W, X( f  c8 P4 n+ Y        size_t        nleft;
7 c$ ^% B- |/ O* f( Y4 a+ F7 O        ssize_t        nread;
4 ]# ]  o' n( |2 p3 s. i7 o3 A. f. |        char        *ptr;
7 b! t* B8 A  ^: B6 r
5 q6 j) l* Y% e# G5 l% s0 [! N        ptr = vptr;
% i' `7 Q  e; ?% z# P% p1 m        nleft = n;/ F9 k5 q7 E. L
        while (nleft > 0) {
5 [1 c8 M7 x# _; D. K  ]                if ( (nread = read(fd, ptr, nleft)) < 0) {7 a7 }- w8 m# q7 ]) c
                        if (errno == EINTR)
2 w0 B6 c5 s, T                                nread = 0;                /* and call read() again */" ]2 N( v, R! _; o  [
                        else4 o. l) e0 _# Y+ S& O8 D. H1 B5 F
                                return(-1);3 ^/ f5 F0 S3 }$ E
                } else if (nread == 0)' k1 B9 o8 s- \( {" h
                        break;                                /* EOF */6 w/ G* j! s7 C  `! M7 ^' ^# B, N, I
$ C; v  `; S) t! O+ S7 t7 s
                nleft -= nread;8 z1 H: M1 E1 s9 M1 U
                ptr   += nread;# |2 a, q. f5 m0 M2 v! j4 O' {
        }
  c; {5 K0 M2 q: U1 P4 u7 Y        return(n - nleft);                /* return >= 0 */
8 A) i6 h& S( K$ C}
1 o  Z' \$ O$ P  E' @9 {7 U
* F" m7 U8 P  k7 ?+ Vint main(void)' K) V& t  |5 U0 M/ L
{" [: l$ K* C% g
        int sockfd, ret;5 S$ S! C0 A% Z! m# X( t
        struct sockaddr_in  servaddr;
' ~. K) t) r& z& p, H0 t        int n;: \/ V, ]+ c1 q5 t
        char buf[512] ;6 G+ J& ^* a/ N7 _
        5 d, R5 b7 C/ s
        sockfd = socket(AF_INET, SOCK_STREAM, 0);' A& L7 a+ R  U1 I: U7 X% {
        if(sockfd < 0){
$ l4 N6 ]' P; S+ O                perror("Socket error");
% @" B: r7 w/ \5 a! h  P! b3 T9 s                return -1;# H; K0 ^( R( m1 y7 h
        }
0 r5 {- e" G/ ]: t" P+ F/ C        
. p- \; q% d8 m) \- [9 A8 E/ L        memset(&servaddr, 0, sizeof(struct sockaddr_in));
! ^$ R! d, {! F" i2 [& t9 `$ W        //bzero(&servaddr, sizeof(servaddr));, Y* w0 D% R  e+ A: Q
        servaddr.sin_family = AF_INET;
/ j; B& ]* v: _( q3 p4 o# M        servaddr.sin_port = htons(SERV_PORT);- v) `6 P$ t  R6 x( \. y. Y
        ret = inet_pton(AF_INET, SERVIPADDR, &servaddr.sin_addr);
; @2 n1 s0 q& a! f8 x        if(ret < 1){
* F' @0 R' S, K( s5 a/ x# R                perror("Inet_pton error");
9 _/ V$ C5 w  o7 h5 f+ z  ?                return -1;0 F( Q' ^* Q  G9 }- g1 a6 X
        }6 P* P7 T  O6 u& d2 `

) P; |( A" z* T  E        ret = connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
7 a  @5 R( V, ~        if(ret < 0){
& O- t! M& U1 }, L) l5 O                perror("Connect error");
4 i' e' q: S7 \6 R2 e& H' Z3 r                return -1;  _5 p6 }( f1 `/ o6 ?6 o7 r5 X
        }5 c# A, @$ o0 @7 W' `

' O- K  C( h1 V* I+ B4 }- `        close(sockfd);% ~$ z& b& W( n$ d+ ]3 M/ O- p
}
5 G' J! Z9 ]. v- m& ]6 x服务器程序编写完以后,为了让inetd能够调用我们的服务器程序,需要修改配置文件。
% x4 d  K) Y% G! i7 H+ l% Z$ k# j  J. z% r5 r
首先,修改/etc/services,增加如下:
" K/ ~% L' e6 l$ G6 z2 u5 C7 I; ~+ ]' I8 }
mytcpser        30001/tcp                        # Used by BGM
4 k' i! Y  C% ]7 r- O2 q; O7 W% u8 `$ }0 X: l$ A6 K
其次,修改/etc/inetd.conf,增加如下:
. D0 Z! e) m/ l' E( E7 F9 f$ J7 o# X3 J& g* N5 y9 a; |
mytcpser stream tcp nowait root /home/bgm/bgmtcpser bgmtcpser
+ l; F* C* W9 l$ v" g( v7 S: q9 e( _2 ~
这里的mytcpser需要和services文件中的第一个字段相同,其次/home/bgm/bgmtcpser为服务器程序所在的路径。/ y& y9 y# O- D% @% R6 G. o

, e0 j6 J  u% J修改完配置文件后,将服务器程序bgmtcpser复制到/home/bgm目录下。
5 w) h" s* O' g) ^) l
3 H7 W+ `! k* X- B使用netstat 来查看是否inetd已经创建端口号为30001的监听套接字:
6 h) _1 N1 `/ M) h/ V* H& V# r
6 j" o  y+ G6 p, |$ S' g7 D[root@BGM /]#netstat -an | grep 30001- k" O7 D$ i6 V5 ?1 Z4 Y# `

! `$ O( P5 H' L9 ztcp        0      0 0.0.0.0:30001           0.0.0.0:*               LISTEN   
2 y( O  k% Z) e2 ~3 p* Z) T. C7 E6 R; s0 `7 ]4 u
然后我们执行客户程序cli,执行完以后我们查看/var/log/messages中的内容:
) v: N$ r6 A# @! VJul 23 13:13:42 BGM user.alert bgmtcpserv[2587]: Connecting from 192.168.0.200:40571
3 Q" A) g5 n) I) T# w
% }" ]5 f3 V6 N+ ~% Q. w这里的"Connecting from。。。"正是由syslog函数打印的。4 X. B7 K3 _; l! W9 Y5 W
4 Z8 {" K% l7 |6 }

) E5 {& s* N' r) O$ H, b) H
6 g/ h0 z; n  m. N7 G1 l  U
% G$ X, J, K3 ?' q' x( \& @' I
, W& Y, T& B' V# E. v' S4 Q0 f1 W; F. R) l5 b$ c/ }
3 P. I  R& n' c8 s2 q. n  b3 F, x

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-10-28 21:28 , Processed in 0.156250 second(s), 26 queries , Gzip On.

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

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

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