Linux服务器程序规范

Linux服务器程序规范

日志

Linux系统日志

服务器的调试和维护都需要一个专业的日志系统

Linux提供一个守护进程syslogd来处理系统日志

现在的Linux系统上使用的都是其升级版rsyslogd

rsyslogd守护进程既可以接受用户进程输出的日志,又能接收内核日志

用户进程通过调用syslog函数生成系统日志,该函数将日志输出到一个UNIX本地域socket类型(AF_UNIX)的文件/dev/log中。rsyslogd则监听该文件以获取用户进程的输出

内核日志在老系统上是通过守护进程rklogd管理,rsyslogd利用额外的模块实现了相同的功能。内核日志由printk等函数打印至内核的环状缓存中。环状缓存的内容直接映射到/proc/kmsg文件中,rsyslogd通过读取该文件获得内核日志

rsyslogd守护进程在接收到用户进程或内核输出的日志后,会将它们输出到某些特定的日志文件中

默认情况下,调试信息保存至/var/log/debug文件中,普通信息保存至/var/log/messages文件,内核消息保存至/var/log/kern.log文件

具体如何存放可以在rsyslogd的配置文件中设置,rsyslogd的主配置文件/etc/rsyslog.conf

image-20211122164818816

syslog函数

#include<syslog.h>

void syslog(int priority,const char* message,...);

//priority设施值域日志级别的按位或
//设施值默认值为LOG_USER1

//日志级别
#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 //调试

//该函数可以改变syslog的默认输出方式,进一步结构化日志结构
#include<syslog.h>
void openlog(const char* ident,int logopt,int facility);
//ident指定的字符串将被添加到日志消息的日期和时间之后,通常被设置为程序的名字
//logopt参数对后续syslog调用的行为进行配置

#define LOG_PID 0x01//在日志系统中包含程序PID
#define LOG_CONS 0x02//如果消息不能记录到日志文件,则打印到终端
#define LOG_ODELAY 0x04//延迟打开日志功能知道第一次调用syslog
#define LOG_NDELAY 0x08//不延迟打开日志功能

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

//程序在开发阶段可能需要输出很多调试信息,发布后又需要将调试信息关闭,可以设置日志掩码,使日志级别大于日志掩码的日志信息被系统忽略
#include<syslog.h>
int setlogmask(int maskpri);
//maskpri指定日志掩码值,该函数始终会成功,返回调用进程先前的日志掩码值

//关闭日志功能
#include<syslog.h>
void closelog();

用户信息

UID、EUID、GID、EGID

  • UID:真实用户ID
  • EUID:有效用户ID

方便资源访问,使得运行程序的用户拥有该程序的有效用户的权限

image-20211122200458286

image-20211122200537221

image-20211122200703523

  • GID:真实组ID
  • EGID:有效组ID
#include<sys/types.h>
#include<unistd.h>

uid_t getuid();//获取真实用户ID
uid_t geteuid();//获取有效用户ID
gid_t getgid();//获取真实组ID
gid_t getegid();//获取有效组ID

int setuid(uid_t uid);//设置真实用户ID
int seteuid(uid_t uid);//设置有效用户ID
int setgid(gid_t gid);//设置真实组ID
int setegid(gid_t gid);//设置有效组ID

进程间关系

进程组

Linux下每个进程都属于一个进程组,除了PID信息外,还有进程组ID(PGID)

//获取指定进程的PGID
#include<unistd.h>
pid_t getpgid(pid_t pid);

//成功使返回进程pid所属进程组的PGID,失败返回-1并设置errno

//每一个进程组都有一个首领进程,其PGID和PID相同。进程组将一致存在,直到其中所有进程都退出或加入到其他进程组中

//设置PGID
#include<unistd.h>
int setpgid(pid_t pid,pid_t pgid);
//将PID为pid的进程的PGID设置为pgid
//如果pid和pgid相同,则有pid指定的进程将被设置为进程组首领
//如果pid为0,则表示设置当前进程的PGID为pgid
//如果pigd为0,则使用pid作为目标PGID
//成功时返回0,失败返回-1并设置errno

//一个进程只能设置自己或其子进程的PGID,当子进程调用exec系列函数后,不能再在父进程中设置PGID

会话

一些有关联的进程组将形成一个会话

#include<unistd.h>
pid_t setsid(void);

//该函数不能有进程组的首轮进程调用,否则将产生错误

//对于调用该函数的进程
//调用进程成为会话的首领,此时该进程是新会话的唯一成员
//新建一个进程组,其PGID就是调用进程的PID,调用进程成为该组的首领
//调用进程将甩开终端(如果有的话)

//成功是返回新进程组的PGID,失败返回-1并设置errno

//Linux进程未提供会话ID的概念,但Linux系统认为其等于会话首领所在的进程组的PGID
//读取SID
#include<unistd.h>
pid_t getsid(pid_t pid);

用ps命令查看进程关系

image-20211122204358674

系统资源限制

//Linux系统资源限制可通过以下函数读取和设置
#include<sys/resource.h>
int getrlimit(int resource,struct rlimit* rlim);
int setrlimit(int resource,const struct rlimit* rlim);

struct rlimit
{
    rlim_t rlim_cur;
    rilm_t rlim_max;
}

image-20211122204726720

改变工作目录和根目录

#include<unistd.h>

char* getcwd(chat* buf,size_t size);
//获取进程当前工作目录
//buf指向的内存用于存储进程当前工作目录的绝对路径,大小由size参数指定
//如果当前工作目录的绝对路径长度超过了size,则getcwd返回NULL,并设置errno未ERANGE
//如果buf未NULL并且size非0,则getcwd可能在内部使用malloc动态分配内存,并将进程的当前工作目录存储在其中
//如果是该情况,则需要自己释放getcwd在内部创建的这块内存
//getcwd成功是返回一个指向目标存储区(buf指向的缓存区或getcwd在内部动态创建的缓存区)的指针,失败返回NULL并设置errno

int chdir(consy char* path);
//改变进程工作目录
//成功返回0,失败返回-1并设置errno

int chroot(const char* path);
//改变进程根目录
//成功返回0,失败返回-1并设置errno

image-20211122205355217

服务器程序后台化

image-20211122205543472

image-20211122205559555

image-20211122205610747

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值