V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
NGINX
NGINX Trac
3rd Party Modules
Security Advisories
CHANGES
OpenResty
ngx_lua
Tengine
在线学习资源
NGINX 开发从入门到精通
NGINX Modules
ngx_echo
GoodRui
V2EX  ›  NGINX

有关 nginx 日志权限的问题请教各位大佬

  •  
  •   GoodRui · 236 天前 · 2491 次点击
    这是一个创建于 236 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Ubuntu Server 22.04 系统

    使用 nginx 官方 apt 源安装

    1. 默认配置文件中的用户是 user nginx;
    2. systemd 服务的配置文件中未指定服务的运行用户及组。
    3. nginx 服务启动后,master 进程用户是 rootworker 进程用户是 nginx
    4. 生成的日志文件在 /var/log/nginx/ 路径下,目录的属主和属组是 root root, 自动生成的 access.log等日志文件的属主和属组是 nginx adm

    使用源码包编译安装

    1. nginx 配置文件和 systemd 配置文件中用户的部分和使用 apt 源安装的情况是一样的。
    2. nginx 服务启动后,进程的用户和 apt 源安装后的情况是一样的。
    3. 生成的logs日志目录在 nginx 程序目录,权限是 root root,里面自动生成的 access.log等日志文件的属主和属组是 root root,但是权限是 644,nginx 可以正常写入日志。

    想知道为什么编译安装的 nginx 生成的日志,属主和属组为什么会是 root? 如何才能让其生成的 log 文件是 nginx 用户?

    因为涉及到日志的处理等问题,如果日志文件的属主是 root,处理起来会很麻烦。

    第 1 条附言  ·  236 天前
    还有一点很不理解:
    网上搜了说,master 进程的用户不受 nginx.conf 配置文件中的 user 用户指定,一般都是 root 。配置文件中的 user 是 worker 进程的用户。而 nginx 日志是 worker 进程写入的。
    那为什么 log 文件的 owner 是 root root ,权限 644 ,nginx 还能正常的写入日志呢?非 root 用户应该是没有写权限的啊?
    第 2 条附言  ·  236 天前

    可以看下 @retanoj 大兄弟的 #9、# 16 两层楼的内容,感觉情况应该是这样的。nginx 的 bug。 经过测试:

    1. 不论 .log 文件的初始情况是什么样的,删除 .log 日志文件之后重启 nginx,自动生成新的 .log 文件属主和属组都是 root root。
    2. 执行 kill -USR1 操作后,之前手动 sudo touch 出的 .log 文件(root root),属主会被改成 nginx.conf 中配置的 user 用户(即变为 nginx root)。
    第 3 条附言  ·  235 天前

    APPEND 最后定稿版绝对不再修改(第一版)

    用 logrotate 日志分割工具试了下,貌似只要 logrotate 分割使用 root 权限,对日志分割和重新生成都无影响。 所以这个问题其实是没什么大的影响。所以官方才十几年也没修?

    32 条回复    2024-05-01 08:12:06 +08:00
    dier
        1
    dier  
       236 天前
    你是不是用 root 编译的源码呢?配置日志文件的权限可以在 nginx.conf 中配置,第一行就有一个配置`user username;`
    nginx 会用这个用户运行 worker 进程,日志也会是这个用户
    qingbaihe
        2
    qingbaihe  
       236 天前
    apt 安装脚本帮你添加了 nginx 用户和配置文件,编译安装的时候就要你自己搞了
    GoodRui
        3
    GoodRui  
    OP
       236 天前
    @dier 感谢~
    编译及安装是写了 shell 脚本,脚本的执行使用了 sudo 提权。脚本很简单,就是包含 tar 解压缩,/configure && make && make install 动作。

    第一条写明了配置文件中已经指定了 user 为 nginx ;
    第三条已经指明了服务运行后 master 进程用户是 root ,worker 进程用户是 nginx ;
    配置文件的权限不存在问题,不在这个帖子讨论范围。发帖的目的只是请教 nginx 的 logs 目录及其 access.log 、error.log 文件的所有权问题。
    retanoj
        4
    retanoj  
       236 天前
    使用源码包编译安装
    nginx 配置文件。。。。情况是一样的
    生成的 logs 日志目录在 nginx 程序目录 而不在 /var/log/nginx 下?

    ngx 启动的时候没用到你的配置吧
    GoodRui
        5
    GoodRui  
    OP
       236 天前
    @qingbaihe 感谢,编译安装时,nginx 用户已经手动创建,和 apt 源安装创建的 nginx 用户都是一样的。
    nginx:x:998:998:nginx user:/nonexistent:/usr/sbin/nologin
    服务运行没有任何问题,本帖主要是想讨论这两种方法,程序生成的 log 文件的属主和属组为什么不一样的问题。

    因为这牵扯到非 nginx 程序本身的,nginx 日志处理问题。比如说用第三方程序分割、归档、检索 nginx 日志。
    dier
        6
    dier  
       236 天前
    那你对比一下 systemd 服务文件`nginx.service`中的内容,是不是 apt 安装的有指定`user`和`group`
    GoodRui
        7
    GoodRui  
    OP
       236 天前
    @retanoj 好吧怪我,把源码安装的情况简写了。
    编译安装后
    1. nginx.conf 中指定的 user 为 nginx ,与用 apt 源安装时的配置文件中一致。
    2. systemd 服务配置中,未指定 User 和 Group ,与用 apt 源安装的情况下的 systemd 配置文件情况一致。

    nginx 启动及工作都正常,没问题,本帖讨论的仅仅是 《生成的 log 日志文件为什么属主和属组不一样》的问题。因为这牵扯到第三方程序处理 nginx 日志。
    adoal
        8
    adoal  
       236 天前
    apt 安装的 nginx ,初始日志文件是安装完后的善后脚本( /var/lib/dpkg/info/nginx-common.postinst )里创建的,每天日志切分后的维护是在 /etc/logrotate.d/nginx 里配置的。这两个操作都把新的日志文件设置成 owner 为 www-data:adm ,设置 mode 为 0640
    retanoj
        9
    retanoj  
       236 天前
    adoal
        10
    adoal  
       236 天前
    我这里说的 www-data ,对应你的 nginx 用户
    GoodRui
        11
    GoodRui  
    OP
       236 天前
    @dier 感谢~

    以下是使用 apt 源安装时自动配置为 systemd 服务的配置文件
    ```ini
    [Unit]
    Description=nginx - high performance web server
    Documentation=https://nginx.org/en/docs/
    After=network-online.target remote-fs.target nss-lookup.target
    Wants=network-online.target

    [Service]
    Type=forking
    PIDFile=/var/run/nginx.pid
    ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf
    ExecReload=/bin/sh -c "/bin/kill -s HUP $(/bin/cat /var/run/nginx.pid)"
    ExecStop=/bin/sh -c "/bin/kill -s TERM $(/bin/cat /var/run/nginx.pid)"

    [Install]
    WantedBy=multi-user.target
    ```

    以下是编译安装时使用的手写 systemd 服务的配置文件

    ```ini
    [Unit]
    Description=Nginx
    After=network-online.target remote-fs.target nss-lookup.target
    Wants=network-online.target

    [Service]
    Type=forking


    PIDFile=/usr/local/nginx/logs/nginx.pid
    ExecStartPre=/usr/local/nginx/sbin/nginx -t
    ExecStart=/usr/local/nginx/sbin/nginx
    # 用于防止出现 pid 文件读取错误,这是个官方 bug
    ExecStartPost=/bin/sleep 0.1

    ExecReload=/bin/kill -s HUP $MAINPID
    ExecStop=/bin/kill -s TERM $MAINPID

    # 是否使用私有的 tmp 目录
    PrivateTmp=true

    # 重启策略
    Restart=on-failure
    RestartSec=5s

    [Install]
    WantedBy=multi-user.target
    ```

    难道是 PrivateTmp=true 这个设置缓存目录为私有这个配置有问题吗?
    GoodRui
        12
    GoodRui  
    OP
       236 天前
    @retanoj 感谢大佬,贴子里说的情况好像很有理。
    那问题来了,我现在用的最新的稳定版 1.26.0 ,那这个问题是无解了吗...那可要了命了
    GoodRui
        13
    GoodRui  
    OP
       236 天前
    @adoal “apt 安装的善后脚本” 是不是只能在安装完成后才能被调用一次?那为什么我两种方法安装的 nginx ,都删除日志文件后,sudo systemctl stop/start nginx ,重启 nginx 让它重新创建日志文件,创建出的文件还是和原来的情况一样呢?即 apt 安装的 nginx ,自动创建的日志是 nginx:adm ;编译安装的 nginx ,自动创建的日志是 root:root 。
    retanoj
        14
    retanoj  
       236 天前
    @GoodRui #12
    要不换吧 ;(

    我下了个 nginx/1.26.0 ,编译安装,user www-data
    跑起来也出你这问题,logs/* 都是 root
    GoodRui
        15
    GoodRui  
    OP
       236 天前
    @retanoj 换是什么意思 /手动笑哭
    在写业务系统的部署脚本,离线部署,有几个公司自己开发的 nginx 模块,换是不可能换的了...要从 centos 换到 Ubuntu ,而且要求规范部署方式,加强安全。以前 centos 都是 root 用户一把梭,所有程序都是 root 起,所有文件都是 root root ,没这档子事...
    retanoj
        16
    retanoj  
       236 天前
    @GoodRui #15
    好吧,你这问题真涨知识(其实我之前也不知道情况是这样)
    给个结论:Nginx 会以 master 进程的属主创建 access.log & error.log ,并且将其文件描述符通过 fork 方式给到子进程( worker ),所以 worker 可以写入而无关权限。
    当发生 log rotate 时,Nginx 会将旧日志权限转变为 nginx.conf 中 user 字段配置的用户。

    至于 apt 装的为啥日志是 nginx:adm ,是因为装好之后 access.log 和 error.log 已经生成好了。你删掉他们再启动 nginx ,会看到还是 root 生成的文件
    retanoj
        17
    retanoj  
       236 天前
    GoodRui
        18
    GoodRui  
    OP
       236 天前
    @retanoj 我是看了有一些类似的相关反馈和讨论,但是没有找到有解决办法。
    而且我很纳闷,为什么这个问题没很多讨论和关注呢?难道大家都是 root 用户一把梭的吗?
    retanoj
        19
    retanoj  
       236 天前
    @GoodRui #18
    也许是合理的吧。
    当前正在写入的日志文件 644 root:root ,从权限角度代表非特权用户能读不能改
    GoodRui
        20
    GoodRui  
    OP
       236 天前
    @retanoj 是啊,非特权用户不能改,那 worker 进程的用户是 nginx ,为什么能呼呼得写入日志呢?
    retanoj
        21
    retanoj  
       236 天前
    @GoodRui #20
    em... 你再看下 #16 或者 #17
    GoodRui
        22
    GoodRui  
    OP
       236 天前
    @retanoj 哦哦谢谢老哥,刚没看到你#16 的回复。如果你这楼说的是对的,那就明白了。我删了 apt 源安装的 nginx 的 log 文件,重启 nginx ,重新生成的 log 文件 owner 确实成了 root root 。那貌似是个无解的问题...
    adoal
        23
    adoal  
       236 天前
    @GoodRui 人肉测试了一下,删掉日志后 systemd 重新启动 nginx.service 新的日志文件是 root 的了……
    不过 logrotate -f 手工强制卷了一下日志,归档完了后,新的日志文件就又是 www-data:adm 了。

    `
    root@asusz97a:/var/log/nginx# ls -al
    总计 12
    drwxr-xr-x 2 root adm 4096 4 月 29 日 20:23 .
    drwxr-xr-x 25 root root 4096 4 月 28 日 00:00 ..
    -rw-r--r-- 1 root root 162 4 月 29 日 20:26 access.log
    -rw-r--r-- 1 root root 0 4 月 29 日 20:23 error.log
    root@asusz97a:/var/log/nginx# cat access.log
    ::1 - - [29/Apr/2024:20:26:35 +0800] "GET / HTTP/1.1" 200 615 "-" "curl/8.7.1"
    ::1 - - [29/Apr/2024:20:26:38 +0800] "GET /1434 HTTP/1.1" 404 153 "-" "curl/8.7.1"
    root@asusz97a:/var/log/nginx# logrotate -f /etc/logrotate.d/nginx
    root@asusz97a:/var/log/nginx# ls -al
    总计 12
    drwxr-xr-x 2 root adm 4096 4 月 29 日 20:26 .
    drwxr-xr-x 25 root root 4096 4 月 28 日 00:00 ..
    -rw-r----- 1 www-data adm 0 4 月 29 日 20:26 access.log
    -rw-r--r-- 1 root root 162 4 月 29 日 20:26 access.log.1
    -rw-r--r-- 1 www-data root 0 4 月 29 日 20:23 error.log
    `
    adoal
        24
    adoal  
       236 天前
    如果系统负载不是很高的话,还有一个办法,让 nginx 把日志写进 syslog ,在 rsyslog 的配置里去指定落盘位置和文件权限,甚至可以转发到中央日志服务器,本机就不管这些糟心事了。
    ShuWei
        25
    ShuWei  
       236 天前
    master 进程在创建 worker 进程的时候,如果需要,会同步创建日志文件并调整日志文件的权限配置,在这些操作之后,才将 worker 进程降权,所以这个时候创建的日志文件的所有者会是高权限的帐户,大部份时候就是 root
    GoodRui
        26
    GoodRui  
    OP
       235 天前
    @adoal 因为开发把一些业务信息写入 error.log ,看用户的数据量,量大的用户一天一个 error.log 就几个 G 了...
    GoodRui
        27
    GoodRui  
    OP
       235 天前
    @adoal 感谢~
    貌似虽然权限有 bug ,但是用 logrotate 分割日志貌似也没什么影响...所以也不用纠结了...需要注意的好像就是 logrotate 的执行权限需要使用 root.
    adoal
        28
    adoal  
       235 天前
    @GoodRui logrotate 可以设置切分的周期,最小单位是每小时切一次。如果日志增长不均匀,怕每小时切一次在低增长时段切得太碎,还可以设置仅超过指定的大小才切分。
    GoodRui
        29
    GoodRui  
    OP
       235 天前
    @adoal 因为业务基本是按天强相关的,不管每天日志割出来是多少 G ,还是按天比较方便,如果按大小或者是每天分割多次,日志用起来会很麻烦。
    adoal
        30
    adoal  
       235 天前
    @GoodRui 哦,我误解你的意思了,以为“量大的用户一天一个 error.log 就几个 G 了...”这句话是嫌按天切分单个文件太大,主贴和后面说“用第三方程序分割、归档、检索 nginx 日志”是想找更细粒度的切法
    adoal
        31
    adoal  
       235 天前
    另外 logrotate 基本上不用自己考虑用什么用户身份手工调用的问题,因为它是放在/etc/cron.xxxxly/ 下面的配置里自动定时调用的
    GoodRui
        32
    GoodRui  
    OP
       234 天前 via Android
    @adoal 首先,如果只是配置 logrotate 分割配置文件让它自动分割的话,所有的分割任务会被打散在凌晨 3:15~3:45 之间的随机时间点执行。我上面有提到这个对于我们的业务来说是不适用的。我们要求必须 0:00~23:59 为一个天日志。所以我们现在目前都是使用定时任务调用 logrotate 执行,精确控制日志的起始时间节点。
    其次,logrotate 的分割任务配置文件中可以指定该任务运的运行用户,会影响分割出的日志文件 owner 和权限。如果这里指定的用户有问题,会导致分割失败,分割后应用程序无权限写入日志文件等问题。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1226 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 18:09 · PVG 02:09 · LAX 10:09 · JFK 13:09
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.