哈嘍大家好,我是鹹魚 今天跟大家分享一個使用 Python 的 logging 模塊寫入日誌文件時遇到的許可權問題,不知道你們有沒有遇到過 ## 1.案例現象 今天上班的時候手機簡訊收到了 zabbix 告警,但是發現了不對勁的地方:微信沒有收到告警信息,按理說簡訊跟微信應該是同時收到告警信息的 鹹魚 ...
哈嘍大家好,我是鹹魚
今天跟大家分享一個使用 Python 的 logging 模塊寫入日誌文件時遇到的許可權問題,不知道你們有沒有遇到過
1.案例現象
今天上班的時候手機簡訊收到了 zabbix 告警,但是發現了不對勁的地方:微信沒有收到告警信息,按理說簡訊跟微信應該是同時收到告警信息的
鹹魚這邊的 zabbix 是通過一個 python 腳本實現連接微信介面並向微信發送告警消息
上 zabbix 看看 action log
發現 zabbix 發送告警到微信的操作執行失敗了,報錯如下:
Traceback (most recent call last):
File "/home/zabbix/alert.py", line 24, in <module>
logger = create_logger(log_path)
File "/home/zabbix/alert.py", line 10, in create_logger
file_handler = logging.FileHandler(log_path)
File "/usr/lib64/python3.9/lib/python3.9/logging/__init__.py", line 1142, in __init__
StreamHandler.__init__(self, self._open())
File "/usr/lib64/python3.9/lib/python3.9/logging/__init__.py", line 1171, in _open
return open(self.baseFilename, self.mode, encoding=self.encoding,
PermissionError: [Errno 13] Permission denied: '/var/log/myapp/myapp_20230525.log'
2.定位問題
在開始定位前先介紹一下 zabbix 發送告警信息到微信的流程:
- zabbix 調用
/home/zabbix/alert.py
腳本實現告警信息發送到微信 /home/zabbix/alert.py
腳本的大體邏輯就是首先通過 logging 模塊將告警內容寫進本地日誌,然後返回一個 logger 對象- 再將 logger 對象以及其他參數傳進
send_msg
函數裡面,將告警信息發送到微信端
python 腳本 alert.py
中創建並寫入日誌文件的代碼如下:
import logging
import time
...
...
def create_logger(log_path):
# 創建一個 logger 對象
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
# 創建一個文件處理器,將日誌寫入指定的文件中
file_handler = logging.FileHandler(log_path)
file_handler.setLevel(logging.DEBUG)
# 創建一個格式化器,定義日誌的格式
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)
# 將文件處理器添加到 logger 對象中
logger.addHandler(file_handler)
return logger
if __name__ == '__main__':
log_path = '/var/log/myapp/myapp_%s.log' % time.strftime('%Y%m%d', time.localtime())
logger = create_logger(log_path)
...
看報錯信息裡面有 PermissionError
,首先定位到應該是許可權問題
看下這個日誌文件的信息
[root@localhost /var/log/myapp]# ll /var/log/myapp/myapp_20230525.log
-rw-r--r-- 1 root root 300 5月 25 14:09 /var/log/myapp/myapp_20230525.log
可以看到屬主屬組都是 root,其他用戶只有讀的許可權
我們再來看一下 zabbix 進程
[root@localhost /var/log/myapp]# ps -ef | grep [z]abbix
zabbix 31076 1 0 3月16 ? 00:00:00 /usr/sbin/zabbix_server -c /etc/zabbix/zabbix_server.conf
可以看到 zabbix 進程是 zabbix 用戶啟動的,因為 /var/log/myapp/myapp_20230525.log
的許可權是644且屬主屬組都是 root
所以說 zabbix 用戶調用 alert.py
腳本時發現寫入日誌因為沒有許可權而失敗,導致腳本運行崩潰
3.排查問題
到這裡基本就能知道是什麼原因了,但是還有一點疑問:只有 /var/log/myapp/myapp_20230525.log
這個日誌的屬主屬組都是 root ,其餘日誌文件都是 zabbix
我們知道,在 Python 的 logging 模塊中,日誌文件的屬主是由操作系統的文件系統決定的,而不是由 logging 模塊本身決定。當使用 logging 模塊創建日誌文件時,它會使用操作系統提供的預設文件創建方式。
這意味著日誌文件的屬主將取決於當前運行 Python 程式的用戶或進程的許可權和身份。
看樣子應該是有人使用 root 用戶執行過這個 python 腳本,導致生成的這個日誌文件 myapp_20230525.log
屬主是 root,後面等 zabbix 自己去執行這個腳本(zabbix 用戶)的時候發現沒有許可權寫東西進 myapp_20230525.log
裡面,這才導致微信收不了告警信息
後面拷打了一下同事(其實是執行了 history
命令看操作記錄 )才知道昨晚同事在終端上手動跑了一下這個 python 腳本,又因為預設登錄用戶是 root,導致生成的日誌文件屬主屬組都是 root
如何解決:修改一下日誌文件的屬主屬組即可
chown zabbix.zabbix /var/log/myapp/myapp_20230525.log