Linux服务器程序规范

概述

除了网络通信外,服务器程序还必须考虑许多其他细节问题,零碎,但基本上是模板式的。比如:

  • Linux服务器程序一般以后台形式运行。后台程序又称守护进程。它没有控制终端,因而也不会意外接受用户输入。守护进程的父进程一般是init进程(PID=1)
  • Linux服务器程序通常有一套日志系统,它至少能输出日志到文件,有的高级服务器可以输出日志到专门的UDP服务器。大部分后台进程都在/var/log下有自己的日志目录
  • Linux服务器程序一般以某个专门的非root身份运行。mysqld, httpd, syslogd等后台进程,并分别有自己的运行账户mysql, apache, syslog
  • Linux服务器通常时可配置的。服务器程序通常处理很多命令选项,如果一次运行的选项太多,则克拉一用配置文件来管理。绝大多数服务器程序都有配置文件并存放在/etc下
  • Linux服务器程序通常在启动时生成一个PID文件并存入/var/run目录中,以记录该后台进程的PID。
  • Linux服务器程序通常需要考虑系统资源和限制,以预测自身能承受多大负荷,比如进程可用文件描述符总数和内存总量等

日志

Linux系统日志

  • 用户日志函数 syslog:生成系统日志,输出到一个UNIX本地域socket类型(AF_UNIX)的文件/dev/log中

  • 守护进程 rsyslogd:接收用户进程输出的日志,又能接收内核日志,监听上述文件以获取用户进程的输出

  • 内核日志函数 printk:打印至内核的环状缓存中,环状缓存的内容直接映射到/proc/kmsg文件中。rsyslogd则通过读取该文件获得内核日志

  • 默认情况下,调试信息保存在/var/log/debug,普通信息保存至/var/log/messages,内核信息:/var/log/kern.log

  • rsyslogd 主配置文件是/etc/rsyslog.conf,主要设置的项包括:内核日志输入路径,是否接受UDP日志,及其监听端口(默认514 /etc/services),是否接受TCP日志及其监听端口,日志文件权限,包含哪些子配置文件

syslog函数

1.作用

与rsyslogd守护进程通信

2.定义

#include <syslog.h>  
void syslog ( int priority, const char* message, ... );    // 可变参数  

3.函数说明

第二个和第三个参数为可变参数,为了结构化输出
priority参数:设施值与日志级别的按位或。设施值的默认值是LOG_USER,可选值如下:

#include <syslog.h>  
#define LOG_EMERG                 0      /* 系统不可用 */  
#define LOG_ALERT                 1      /* 报警,需要立即采取动作 */  
#define LOG_CRIT                  2      /* 非常严重的情况 */  
#define LOG_ERR                   3      /* 错误 */  
#define LOG_WARNING               4      /* 警告 */  
#define LOG_NOTICE                5      /* 通知 */  
#define LOG_INFO                  6      /* 信息 */  
#define LOG_DEBUG                 7      /* 调试 */  

4.函数openlog

  1. 作用:改变syslog的默认输出方式,进一步结构化日志内容
  2. 声明
#include <syslog.h>  
void openlog ( const char* ident, int logopt, int facility );  
  1. 函数说明
    ident:指定的字符串将被添加到日志消息的日期和时间之后,通常被设置为程序的名字。
    logopt:对后续syslog调用的行为进行配置,可取下列值的按位或:
#define    LOG_PID        0x01            /* 在日志消息中包含程序PID */  
#define    LOG_CONS    0x02               /* 如果消息不能记录到日志文件,则打印至终端 */  
#define    LOG_ODELAY    0x04             /* 延迟打开日志功能直到第一次调用syslog */  
#define    LOG_NDELAY    0x08             /* 不延迟打开日志功能 */  

facility:修改syslog函数中的默认设施值

函数setlogmask

  1. 作用:使日志级别大于日志掩码的日志信息被系统忽略
  2. 函数声明
    #include <syslog.h>  
    int setlogmask( int maskpri );  
  1. 函数说明:
    maskpri:指定日志掩码值。
    该函数始终会成功,返回调用进程先前的日志掩码值。
  2. 举例
    setlogmask(LOG_ERR); //仅仅记录ERR级别的日志消息
    setlogmask(LOG_UPTO(LOG_ERR)); //记录ERR以及之前的所有日志的消息[0,3]
  3. 关闭日志功能:
     #include <syslog.h>  
     void closelog();  

用户信息

1. UID, EUID, GID, EGID

Tables Are get / set
UID 真实用户ID getuid() / setuid(uid_t uid)
EUID 有效用户ID geteuid() / setuid(uid_t uid)
GID 真实组ID getgid() / setuid(gid_t gid)
EGID 有效组ID getgeid() / setuid(gid_t gid)

一个进程拥有两个用户ID,UID,EUID。EUID存在的目的是为了方便资源的访问, 它使得运行程序的用户拥有该程序的有效用户权限

2. 切换用户

以root身份启动的进程切换为以一个普通用户身份运行

扫描二维码关注公众号,回复: 1925497 查看本文章
static bool switch_to_user(uid_t user_id, gid_t gp_id)
{
    if((user_id == 0) && (gp_id == 0))
        return false;

    gid_t gid = getgid();
    uid_t uid = getuid();
    if( ( (gid != 0) || (uid!= 0)) && (( gid != gp_id) || ( uid != user_id )) )
        return false;

    if(uid != 0) 
        return false;
    if((setgid(gp_id) < 0) || setuid(user_id) < 0))
        return false;
    return true;
}

进程间关系

(未完待续…)

猜你喜欢

转载自blog.csdn.net/chuxin126/article/details/77925562
今日推荐