作者:hi347 | 来源:互联网 | 2023-06-24 09:18
文章目录服务器程序规范日志rsyslogd守护进程syslog函数openlog函数setlogmask函数closelog函数用户进程间的关系进程组会话系统资源限制改变工作目录和
文章目录 服务器程序规范 日志 rsyslogd 守护进程 syslog函数 openlog函数 setlogmask函数 closelog函数 用户 进程间的关系 进程组 会话 系统资源限制 改变工作目录和根目录 服务器程序后台化
服务器程序规范 Linux
服务器程序一般以后台进程(守护进程[daemon
])形式运行。它没有控制终端,因此不会意外接受到用户输入,守护进程的父进程通常是 init
进程(PID为1)。服务器的调试和维护都需要一个专业的日志系统,Linux
常用一个守护进程 rsyslogd(syslogd的升级版)
来处理系统日志。 Linux
服务器程序一般以 非root
的身份运行。如:mysqld
、httpd
、syslogd
等后台进程分别拥有自己的运行账户 mysql
、apache
和 syslog
。Linux
服务器程序通常能处理很多命令行选项,如果一次运行的选项太多,那么可以用配置文件来管理。配置文件一般放在 /etc
目录下。Linux
服务器程序通常在启动时会生成一个记录该后台进程 PID
的文件并存入 /var/run
目录中。例如: syslogd
的 PID
文件是 /var/run/syslogd.pid
。 日志 rsyslogd 守护进程 既能接受用户进程输出的日志,也能接受内核日志。
用户进程调用 syslog函数
将日志输出到一个 UNIX
本地域 socket
类型(AF_UNIX
)的文件 /dev/log
中,rsyslogd
则监听该文件以获得用户进程的输出。 内核日志由 printk
等函数打印至内核的 环状缓存(ring buffer)
中,环状缓存的内容直接映射到 /proc/kmsg
中,rsyslogd
读取该文件以获得内核日志。
syslog函数 应用程序通过 syslog函数
与 rsyslogd
守护进程通信:
# include void syslog ( int priority, const char * message, . . . ) ;
限于 LOG_USER
设施值对应的日志级别有:
# include # 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
openlog函数 改变 syslog
的默认输出方式,进一步结构化日志内容:
# include void openlog ( const char * ident, int logopt, int facility ) ; # define LOG_PID 0x01 # define LOG_CONS 0x02 # define LOG_ODELAY 0X04 # define LOG_NDELAY 0x08
setlogmask函数 程序在开发阶段可能需要输出很多调试信息,而发布之后又需要将这些调试信息关闭。
解决这个问题的方法并非是在发布后删除调试代码(日后可能还需要用到),而有更简单的做法——设置日志掩码 ,使日志级别 大于掩码 的日志信息 被系统忽略。
setlogmask函数
就用以设置日志掩码:
# include int setlogmask( int maskpri ) ;
closelog函数 用以关闭日志功能:
# include void closelog ( ) ;
用户 服务器中不同的用户有不同的权限,因此 获取or设置 当前进程的 真实用户ID(UID)、有效用户ID(EUID)、真实组ID(GID)、有效组(EGID) 就尤为重要:
# include # include uid_t getuid ( ) ; uid_t geteuid ( ) ; gid_t getgid ( ) ; gid_t getegid ( ) ; int setuid ( uid_t uid ) ; int seteuid ( uid_t uid ) ; int setgid ( gid_t gid ) ; int setegid ( gid_t gid ) ;
一个进程有两个 用户ID: UID
和 EUID
。EUID
方便了资源访问:使得 运行程序的用户 拥有 该程序的有效用户 的权限。如:任何用户都可以通过 su程序
修改自己的账户信息,这就不得不访问需要 root
权限的 /etc/passwd
文件。那么以普通用户身份启动的 su程序
如何能访问/etc/passwd
文件呢?
用 ls
命令可以查看到,su程序
的所有者是 root
,且被设置了 set-user-id标志
,即任何普通用户运行 su程序
时,su程序
的有效用户为 root
。有效用户为 root
的进程被称为 特权进程(privileged processes) 。
类似的,EGID
为运行目标程序的组用户提供有效组的权限。
进程间的关系 进程组 Linux
下每个进程都隶属于一个进程组,PGID
即为它的 进程组ID 。进程组将一直存在,知道其中所有进程都退出或者加入到其他线程组。每个进程组都有一个首领进程,其 PGID
和 PID
相同。
# include pid_t getpgid ( pid_t pid ) ; int setpgid ( pid_t pid, pid_t pgid ) ;
一个进程只能设置自己或者子进程的 PGID
,子进程调用 exec
系列函数后,父进程不再能设置它的 PGID
。
会话 一些有关联的进程组能形成一个会话 (session
),下面的函数用以创建一个会话:
# include pid_t setsid ( void ) ;
该函数不能由进程组的首领进程调用,否则产生一个错误。对于非组首领的进程,创建新会话的同时且有如下额外效果:
调用进程成为会话的首领,此时该进程是新会话的唯一成员。 新建一个进程组,其 PGID
就是调用进程的 PID
,调用进程成为该组的首领。 调用进程将甩开终端(如果有的话)。 Linux
进程并未提供所谓 会话ID(SID)
的概念,但将会话首领所在的进程组的 PGID
视为 SID
,并提供了如下函数来读取 SID
:
# include pid_t getsid ( pid_t pid ) ;
系统资源限制 Linux 上运行的程序都会受到资源限制的影响,比如物理设备限制(CPU数量、内存数量等)、系统策略限制(CPU时间等),以及具体实现的限制(文件名的最大长度)。这些系统资源限制可以通过下面的函数来读取 和设置 :
# include int getrlimit ( int resource, struct rlimit * rlim ) ; int setrlimit ( int resource, const struct rlimit * rlim ) ; struct rlimit { rlim_t rlim_cur; rlim_t rlim_max; } ;
除上述外:
还可以使用 ulimit
命令修改当前 shell
环境下的资源限制(软限制或/和硬限制),这种修改将对该 shell
启动的所有后续程序有效。 还可以通过修改配置文件来改变系统软限制和硬限制,这种修改是永久的。 改变工作目录和根目录 # include char * getcwd ( char * buf, size_t size ) ; int chdir ( const char * path ) ; int chroot ( const char * path) ;
服务器程序后台化 让一个进程以守护进程的方式运行:
# include int daemon ( int nochdir, int noclose) ;