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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
本文将描述在使用inetd守护进程时,如何通过syslog函数打印消息到日志文件。; e+ Y# F. \+ d" d
+ C6 D! L5 X" z% D
为什么需要这样做呢?根据《UNIX网络编程 卷1:套接字联网API》一书第13章的描述:由于守护进程没有控制终端,它们不能把消fprintf到stderr上。
3 K; `* }5 V* [- I' R2 M/ U+ S
, |/ @+ w- o5 H& f( S从守护进程中登记消息的常用技巧就是调用syslog函数。) K8 Z" L8 H1 g" V9 p

3 R& b  O) J2 Q6 d而sysolog函数需要syslogd服务的支持。因此在编译busybox时需要使能syslogd。
4 m$ D2 p, W( `7 X0 W7 x. f5 F6 n( Y4 ?" H. h5 W
4 V! a* {" L7 f2 b6 v
; I) u" o8 z6 u7 z- W0 x

$ i3 e" j4 Y: Q/ Y2 C  G' N( j1 T9 S6 o0 Z' z7 f) S
Linux系统启动后,需要打开syslogd服务。先来看看syslogd的命令选项:
! ]; K' A1 R- Y0 z# x7 F9 _- y) g1 s: V) K
[root@BGM /]#syslogd -h; R$ i+ I) d, h1 w% h
syslogd: invalid option -- 'h'% ~1 [* x, t. ~0 V7 `) G  h1 G
BusyBox v1.16.0 (2013-04-15 16:07:27 CST) multi-call binary.( [( n: `  w% }4 z7 B
9 W, f0 @( R4 E
Usage: syslogd [OPTIONS]" w" J7 J+ g/ l( d( F" O/ U4 w1 X
0 _: t6 H( S6 p" @
System logging utility.
8 R! J; g/ F" u4 VNote that this version of syslogd ignores /etc/syslog.conf./ k8 j& S- x) z

; o. R2 u! r4 X0 [- ~  sOptions:
2 I' |6 B! h& F9 I        -n              Run in foreground7 Q9 Q% F: p  z
        -O FILE         Log to given file (default:/var/log/messages)) m# T# w0 g7 A: ~  O9 q
        -l n            Set local log level
  h; v" k  [( d6 Z* ]) L" G        -S              Smaller logging output5 p4 Y/ G: e3 F! L
        -s SIZE         Max size (KB) before rotate (default:200KB, 0=off)
, J8 N- B, ]: Q        -b N            N rotated logs to keep (default:1, max=99, 0=purge)+ o0 J: f) t# n& U9 V
        -R HOST[: PORT]  Log to IP or hostname on PORT (default PORT=514/UDP)
9 w8 b; V. ~$ L! a2 P+ O        -L              Log locally and via network (default is network only if -R)
7 J( E9 i& a' @' y; q  ~        -D              Drop duplicates* ^) Y  _' K4 J; J& S" N8 j
        -C[size(KiB)]   Log to shared mem buffer (read it using logread)/ o! k7 V# N  I) _5 A" e

) I% f8 e; I. Q2 ~这里我们注意到该syslogd不支持/etc/syslog.conf文件。
& b" ?6 p7 @8 A! w, q) [' s* _& T( c4 @( z7 S) W$ \
我们需要使用-L选项,让消息输出到本地(locally),其次其默认的本地输出文件为/var/log/message,1 Q8 ^& c; S7 W
/ t" z  C9 b  _. ~( S# p
如果要修改输出文件,则使用-O选项。
) K! v" E6 j& I$ w" [6 v, F' s9 E- K
. H4 N( j& w* ?因此,我这里使用的syslogd命令如下:
; Y- z  C6 j4 e
3 n5 n: \" w% a# x* \2 P" \: \/sbin/syslogd -L/ }: D7 t7 \$ H: ]: G9 j1 ~$ j, P

$ x! d+ K. l! v  f- |这里建议将该命令添加到系统的启动脚本中。
, [  c5 a$ B( L; _8 b& d/ ?0 e& D
* A5 b5 a  p) {2 y为了测试函数需要编写一个简单的TCP服务器程序和相应的客户程序,参照《UNIX网络编程 卷1:套接字联网API》的13.6小结编写测试用例," Y9 {. c3 H- J/ D  Z
" r! h1 x- `4 E
程序如下:5 p2 P7 R) }, N/ T; b  e7 V

& C  \, S! X9 I: Y/ D6 E# p0 S' i服务器程序:- v1 {, A* z+ X& G. G) j9 c; o" ]
& R) [5 e* Z; q* ^% \( d
int main(void)
, t- F- Y6 [/ G& y, b! u{
$ `" c1 {6 z' a- f1 W+ g; y, _' k        socklen_t len;5 z* I7 q# p/ V. Z. G+ ?
        struct sockaddr *cliaddr;
3 E" I$ h# g  H/ {- u" e5 p        char buf[MAX_TCPSERV_BUF];# M+ ~- w9 r7 ?) K
) ^, M) o1 y, Y; }& ]- |/ H- G% m
        int ret, tmp;
! z! ^) e& t' b- x2 g
0 ~/ C4 s# H/ ]        openlog("bgmtcpserv", LOG_PID, 0);
, j2 I( ?( b8 }1 ~' }( D3 z% ~9 j' D1 j) r( {6 F% e4 r& v5 n2 p
        dc = malloc(sizeof(struct data_content));! t2 ^/ i; T1 J
        if(!dc){) i+ I; T+ |: E& p( w
                perror("Unable to malloc data_content ");
, d# ^) E# X3 B- a9 P( c                exit -1;
3 z) `; g5 c% F$ b5 M' j        }' j) q# x3 ~9 h6 L

: K$ Z2 t7 y) f. W) w        cliaddr = malloc(sizeof(struct sockaddr_storage));
7 M  o, ]9 H& p/ |  m! _4 Y0 G        if(!cliaddr){8 ~) X5 Z+ `; O7 T
                perror("Unable to malloc sockaddr_storage ");
: W! s( Z7 l4 x. H& u- w* U                exit -1;
" e8 J5 }4 J, }! ~9 O9 {0 a        }4 J# R+ h. r( v# x0 u. ]- N

" d3 `: v: H8 x; `' P        len = sizeof(struct sockaddr_storage);
4 A  v5 M. Z8 P9 m$ E; R- J2 l        if (getpeername(0, cliaddr, &len) == -1){) J. |9 \% Y- k% O+ N. n' s7 O
                perror("Getpeername error ");7 t+ v7 s# P: I, ]
                exit -1;! V( T7 n8 Y$ y3 x, ^
        }! n1 r' Z7 b- Q  l4 s" z( V
        
9 |8 q- Y" c1 I, G5 e; j' [7 [        syslog(LOG_USER|LOG_ALERT, "Connecting from %s\n", Sock_ntop(cliaddr,len));
; s# \3 m0 n) x8 s        
3 e  V* P7 a' `& S        close(0); # y6 n& `: e$ [* t; |
        closelog();# g3 A( J% p& T
        exit(0);
+ U* m6 Q) O4 t}
# u0 D! ?) o* y2 m0 R- {/* include sock_ntop */
3 K1 ~6 E5 D# ^# \+ S& {6 w/ t7 R0 dchar *
: x3 Y! J5 \/ I' ?! F. _) tsock_ntop(const struct sockaddr *sa, socklen_t salen)
, I0 q* Z" b4 w1 n{+ l2 f' L8 q9 Y: m" P
    char        portstr[8];  B; v) `+ K) r* r0 B' Y+ n& u" G
    static char str[128];        /* Unix domain is largest */
; I- C; k* [+ Y/ m1 e
* {- c1 q6 w  O8 u8 H$ G' U    switch (sa->sa_family) {: y5 z' C% y9 ~# {' Q% W# E0 q
    case AF_INET: {; r' m- e% @2 E3 T2 d- [% y# C
        struct sockaddr_in    *sin = (struct sockaddr_in *) sa;! s0 x3 j/ v: J* B

( u4 d0 B" c$ m0 P0 L7 x6 s( H' R        if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == NULL)
- R* ?7 ]2 X5 `  p2 T/ P1 |            return(NULL);
0 S6 F) j4 v' o/ d7 ?  P        if (ntohs(sin->sin_port) != 0) {8 y) G, M+ n3 }7 w
            snprintf(portstr, sizeof(portstr), ":%d", ntohs(sin->sin_port));' b, n+ ^. n) u$ n9 D
            strcat(str, portstr);
3 Z# {. b4 j& R. `        }3 D0 n6 J. o! w% H" R) ]
        return(str);
2 ~2 S% H4 g# v1 i+ Z' P  ~    }
- U5 H$ \' @+ K; R/* end sock_ntop */
' `8 {6 U; P+ D% E6 m; ]
( E6 q5 R7 A8 h#ifdef    IPV6
( U' m3 T5 t2 P& a) ]    case AF_INET6: {; `' Y) G+ }: f3 d+ z+ `- v# ?
        struct sockaddr_in6    *sin6 = (struct sockaddr_in6 *) sa;
6 \& _7 {: d2 [3 n! s' O4 D1 k
( T" J6 k% W. G5 B4 ]! {        str[0] = '[';
# R! p+ `+ O# A' V% [        if (inet_ntop(AF_INET6, &sin6->sin6_addr, str + 1, sizeof(str) - 1) == NULL)
( r( y0 O$ u! {" P            return(NULL);
+ s- ^5 D0 E) D. @: a  T        if (ntohs(sin6->sin6_port) != 0) {
: ^" A1 M4 V! h" k5 m            snprintf(portstr, sizeof(portstr), "]:%d", ntohs(sin6->sin6_port));
1 q2 a6 a" V8 K            strcat(str, portstr);& S6 h+ u; P1 L0 M4 C- U
            return(str);
5 s1 H3 k8 R) r9 G        }
0 w' A9 S- R" {! L0 ]; Z0 c! R6 ~9 T        return (str + 1);) `& j4 p2 B5 Q# m* e, n9 p# l! i
    }
1 b4 I& y4 t9 t#endif
# p( P+ P8 |7 ^/*
6 J4 s$ t; z9 l0 G; H#ifdef    AF_UNIX) w5 D4 R# W4 H7 Z% k5 d* Y
    case AF_UNIX: {
; t1 Q  f, J+ ^4 j7 {        struct sockaddr_un    *unp = (struct sockaddr_un *) sa;  v4 @* n* `) a: e
             OK to have no pathname bound to the socket: happens on
8 x, {  @! \* G* W               every connect() unless client calls bind() first. $ S) }" W2 ~+ Q# S9 M4 b4 R8 K
        if (unp->sun_path[0] == 0)& Z& V3 }) d. g. p! D
            strcpy(str, "(no pathname bound)");
3 {# ]* N4 z3 ~  e        else8 Z5 y. m" {/ g" L5 R+ i  C5 A( l% l: v
            snprintf(str, sizeof(str), "%s", unp->sun_path);# E, \# \4 F5 e6 D0 P& F- v6 w
        return(str);
- x3 {# q4 Y1 {& r) b6 J    }
6 Q. F$ R# _3 v; B, D#endif*/% M& Z  `1 q* k$ p1 {0 k8 M
4 [! l( r/ R$ Y% _* N* n' v
// #ifdef    HAVE_SOCKADDR_DL_STRUCT+ M. e0 s' _" l: G4 p: H
//     case AF_LINK: {7 P# N* q: o( F' W; L7 K
//         struct sockaddr_dl    *sdl = (struct sockaddr_dl *) sa;
  o6 t3 h& w; Z5 J! o
4 r8 D) q1 m  i6 s/ S0 W//         if (sdl->sdl_nlen > 0)5 M8 S) p) l* O4 `9 }
//             snprintf(str, sizeof(str), "%*s (index %d)",
8 e1 w5 s7 \" F' r//                      sdl->sdl_nlen, &sdl->sdl_data[0], sdl->sdl_index);
' x" T1 ~+ ^  z0 R5 w//         else$ D6 \2 F4 a, d* @# y
//             snprintf(str, sizeof(str), "AF_LINK, index=%d", sdl->sdl_index);
9 T& k: V2 \. Z# Z6 k$ n$ @4 n9 Q//         return(str);
- b: U" t( V( Q- R+ k# G# f//     }! O  Y* B: v: D- U, C7 k1 `
// #endif
* Z! A/ c% L2 x1 A; F( y9 Q0 o    default:8 {- N2 Y" _' U; m
        snprintf(str, sizeof(str), "sock_ntop: unknown AF_xxx: %d, len %d",
8 G" O; b' B/ W0 R2 T" i5 t                 sa->sa_family, salen);, r3 v2 {  E; @/ u: N' f4 J
        return(str);, l, e, j8 y0 x2 o
    }7 Y) S( \1 k6 l8 K3 Q8 a9 g
    return (NULL);! [- _' X$ p$ e; z$ V( z
}' v# e- P+ I4 C: h% q
( Y+ t( K7 H& X: {. q5 Q
char *
9 t$ X$ p$ ^& Z" v3 `+ k/ }5 ?Sock_ntop(const struct sockaddr *sa, socklen_t salen)
% @8 m* u0 Q' y+ N% K* D7 W{
/ z: U) M4 [. x# e8 I" |  \, G    char    *ptr;
$ i0 w3 S! d, h& k% O$ T6 `5 A" c/ n) C8 w( L! U3 q) y% s
    if ( (ptr = sock_ntop(sa, salen)) == NULL)
" a( `' s) f1 `' {        perror("sock_ntop error");    /* inet_ntop() sets errno */7 I9 `8 O) V' ~
    return(ptr);
% f! B, P4 a- J3 @3 e, p( M}* C' V2 y" B' l. w
& u8 O8 \$ _3 X+ F3 {9 k
客户端程序:  h1 x# g) M' c
#define SERV_PORT 30001
* K0 e% L8 `$ b' n# ~. I7 {' W7 ~#define SERVIPADDR "192.168.0.200"
$ [/ d% q3 X- r- S. [
; ?8 D: t: n; t5 Hssize_t                                                /* Read "n" bytes from a descriptor. */+ c( ]6 w6 y6 V$ |" f
readn(int fd, void *vptr, size_t n)9 `5 a2 l! b8 b: L& D
{
6 l4 `' a3 }  ?) Z+ o, j3 U        size_t        nleft;
7 p& R5 |1 j0 M$ `: W        ssize_t        nread;
5 W" c: U  `; }6 B+ e! {6 x3 Z7 c        char        *ptr;+ q/ d) A4 L, B3 U# S

, _% |2 W" F4 \9 `, b        ptr = vptr;5 C1 c* ]/ k1 i; k
        nleft = n;
( d# y. P; i' [% x        while (nleft > 0) {
5 n& C6 [& N; T0 Y. J/ v8 E- ~                if ( (nread = read(fd, ptr, nleft)) < 0) {$ i" N0 M/ n5 O
                        if (errno == EINTR)
0 y4 e. O0 ?6 m  y: Y                                nread = 0;                /* and call read() again */7 A- |) \+ c4 X5 ?% l1 Q
                        else6 O" B" w0 P, G/ d' Y  P
                                return(-1);
+ Q& S8 d7 ~5 d                } else if (nread == 0)
9 y. t' d# w# U  M8 u6 M                        break;                                /* EOF */$ z4 {: m% Z" g: h2 Q

1 [! g  @" Q. U/ ?                nleft -= nread;* W9 l" g2 P( t6 g2 d4 d5 a
                ptr   += nread;7 |% W/ H1 _+ y" Z6 f3 p5 d
        }- C/ O5 C  s5 S# w4 I% x6 u( L4 a
        return(n - nleft);                /* return >= 0 */
+ C3 T# r% N* P  ]}
/ G6 c# H, F1 F/ }3 a: \
4 A# X- d; k. I5 q' U9 n6 Tint main(void)9 n( y1 b& G. p  ~, {+ M5 B* D2 A
{
/ h3 f6 _, N  |8 ?        int sockfd, ret;
5 m) Q) n8 U; p( v' V# @/ n3 {        struct sockaddr_in  servaddr;
- o6 C2 t% ^5 {% {) ]        int n;
$ X% I9 _9 S: u$ J7 {& ?        char buf[512] ;
+ Q: b# d8 n& |1 B: H; N        
4 E/ a3 _1 E; Z4 H# z        sockfd = socket(AF_INET, SOCK_STREAM, 0);& W* G; k5 _/ z+ G# V
        if(sockfd < 0){
3 g7 B' ]: L" v5 I                perror("Socket error");9 P6 S& u3 ?0 l& v
                return -1;/ f; z. b( }. F! k3 X
        }( t+ _" y# g2 Q5 t# }
        . c& Q, r- ?$ s  Z: P' v' \4 G
        memset(&servaddr, 0, sizeof(struct sockaddr_in));
  a( v) T& y; D3 b" Y        //bzero(&servaddr, sizeof(servaddr));8 f. r# B5 x2 P
        servaddr.sin_family = AF_INET;# e" C8 k7 @1 f# T' |( _' {
        servaddr.sin_port = htons(SERV_PORT);) Y( a. F6 J& L- K- R' F
        ret = inet_pton(AF_INET, SERVIPADDR, &servaddr.sin_addr);0 z) T2 f. C2 y. N* A
        if(ret < 1){
3 k- G% ?1 u2 d' O+ E! Y! G3 {& g+ r* H                perror("Inet_pton error");
6 A+ i& b! G3 p* z. ]5 c% q+ b/ u                return -1;6 L* z( n4 V4 l; l( d( b1 U! C
        }
* N- A' Z% D+ X
. O  U6 h6 a3 y2 n: w/ H7 A        ret = connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
. d# p( F2 n& D        if(ret < 0){. `+ A7 U. M9 C1 [+ i; {9 ^- E
                perror("Connect error");# G7 h3 I) [2 L8 q# E5 f* E- q1 u
                return -1;
2 G3 M' C# O3 B2 x  ], L1 t        }, a7 x# u8 T' q0 N. r2 S, Y
, M2 [) F- b. @5 w! E2 a# G
        close(sockfd);! M8 K. q2 Y% v# u' p6 t2 ?
}- @6 s  n( B, n& x
服务器程序编写完以后,为了让inetd能够调用我们的服务器程序,需要修改配置文件。
3 v" Y8 \) ^  S: p
; o' k9 ], q* w+ N% x7 G首先,修改/etc/services,增加如下:0 g: [4 _. e6 |$ H
. J0 G0 Q7 J5 G8 j7 `# T3 C" d
mytcpser        30001/tcp                        # Used by BGM) O  d& T0 s1 ~# O

3 O5 V  N  q/ g' P# d% F) [5 r. i其次,修改/etc/inetd.conf,增加如下:
2 u4 B3 {9 z0 y6 {* c) v( b$ K' e9 `) C) L8 d9 i) S
mytcpser stream tcp nowait root /home/bgm/bgmtcpser bgmtcpser6 ^1 Y: L8 Q5 f/ R, Y9 e+ s

  [5 a/ n! u$ N4 F6 v这里的mytcpser需要和services文件中的第一个字段相同,其次/home/bgm/bgmtcpser为服务器程序所在的路径。9 Z( E4 ~1 N* h

4 q& ~! O4 j6 J  K修改完配置文件后,将服务器程序bgmtcpser复制到/home/bgm目录下。
8 ?! g  C0 k* O% ]. l* ]0 ~, X. M$ [9 I
使用netstat 来查看是否inetd已经创建端口号为30001的监听套接字:
+ Q- u# a9 b" ?) S- y% s. J! h0 N  @9 F8 K  Y+ J
[root@BGM /]#netstat -an | grep 30001& s0 V$ q, f4 z1 p! |& G$ r

- ?2 p" ^  e" R8 ?: V* Vtcp        0      0 0.0.0.0:30001           0.0.0.0:*               LISTEN   
& M1 j/ b$ ^2 g; P7 O% ]+ p' ?
! X, L$ l8 i$ O0 f) `/ X然后我们执行客户程序cli,执行完以后我们查看/var/log/messages中的内容:
& Z- q5 N3 Z/ B+ k9 x; QJul 23 13:13:42 BGM user.alert bgmtcpserv[2587]: Connecting from 192.168.0.200:40571
; i0 m% q6 K; O4 i! z% c- [
# |& ?4 Y" w7 R: e5 t这里的"Connecting from。。。"正是由syslog函数打印的。
. _0 f/ L- w' C/ `
( Y, K7 Y  T) H  z) I
% k0 `" J+ N+ w
! s) L+ |' {; v* H2 s5 o
$ h8 Y# G$ d# K% }5 G# s" z7 ?" p# f' V# f9 m/ K$ ^
: Z0 |* I. ~9 N% `
2 b* D# [. z" `

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

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

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

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

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