Ceph日誌歸檔

Ceph日誌管理

Ceph產生的日誌是怎麼進行歸檔或者處理的呢?

在Linux下,基本上都是使用logrotate日誌管理工具來處理日誌的。關於logrotate的詳解可以通過這篇文章瞭解: http://www.ywnds.com/?p=5471

關於Ceph的日誌處理的logrotate的配置,可以查看/etc/logrotate.d/ceph文件,源碼中的話在ceph/src/logrotate.conf中。

我們來看一下這個配置文件:

/var/log/ceph/*.log {
    rotate 7
    daily
    compress
    sharedscripts
    postrotate
        killall -q -1 ceph-mon ceph-mds ceph-osd ceph-fuse radosgw || true
    endscript
    missingok
    notifempty
    su root ceph
}

從上面的這個logrotate配置中,我們可以看出:

Ceph日誌是保留7天;

每天做一次壓縮、轉儲;

其中的命令:

postrotate
    killall -q -1 ceph-mon ceph-mds ceph-osd ceph-fuse radosgw || true

postrotate是指每次做完轉儲之後要做的命令。killall這條命令就是要執行的。

乍一看這條命令,爲什麼是向ceph的那些進程發送信號呢,豈不是關掉那些進程嗎。

killall的命令中-1就是具體的信號,通過man 7 SIGNAL可以看到信號1就是SIGHUB信號,默認SIGHUP信號的處理是直接中斷服務的。

難道真是停止所有ceph服務嗎?肯定不對,我們就去看看ceph-mon ceph-osd的代碼,看怎麼處理這個信號的。

ceph-mon ceph-osd服務的入口函數都是ceph_mon.cc或者ceph_osd.cc,下面我們以ceph-osd服務來看:

ceph_osd.cc:

int main(int argc, const char **argv)
{
    ...
    register_async_signal_handler(SIGHUP, sighup_handler);
    ...
    unregister_async_signal_handler(SIGHUP, sighup_handler);
    ...
    
}

從main函數中可見,註冊了一個信號處理函數,對SIGHUP信號進行處理,回調處理函數是sighup_handler:

void sighup_handler(int signum) 
{                               
  g_ceph_context->reopen_logs();
}

reopen_logs函數如下:

void CephContext::reopen_logs()           
{                                         
  ceph_spin_lock(&_service_thread_lock);  
  if (_service_thread)                    
    _service_thread->reopen_logs();       
  ceph_spin_unlock(&_service_thread_lock);
}

然後調用到了reopen_logs:

void reopen_logs()       
{                        
  Mutex::Locker l(_lock);
  _reopen_logs = true;   
  _cond.Signal();        
}

該函數中,將_reopen_logs這個變量設置爲true,並且,喚醒了等待_cond的函數。

通過搜索_reopen_logs變量,可以看到在如下的函數中處理:

void *entry()                                              
{                                                          
  while (1) {   
    if (_cct->_conf->heartbeat_interval) {                 
      utime_t interval(_cct->_conf->heartbeat_interval, 0);
      _cond.WaitInterval(_cct, _lock, interval);           
    } else                                                 
      _cond.Wait(_lock);                                   
  
    if (_reopen_logs) {                                    
      _cct->_log->reopen_log_file();                       
      _reopen_logs = false;                                
    }                                                      
    ...
}

該函數是CephContextServiceThread類型的thread的線程入口函數,在死循環中,會根據heartbeat時間間隔,來進行心跳處理,同時,也在等待_cond這個條件變量,上面的reopen_logs函數喚醒的就是這個。進而,調用了reopen_log_file()函數。

這裏的reopen_log_file是具體的reopen log函數:

void Log::reopen_log_file()
{
   if (m_fd >= 0)                                                           
     VOID_TEMP_FAILURE_RETRY(::close(m_fd));                                
   if (m_log_file.length()) {                                               
     m_fd = ::open(m_log_file.c_str(), O_CREAT|O_WRONLY|O_APPEND, 0644);    
     if (m_fd >= 0 && (m_uid || m_gid)) {                                   
       int r = ::fchown(m_fd, m_uid, m_gid);                                
       if (r < 0) {                                                         
         r = -errno;                                                        
         cerr << "failed to chown " << m_log_file << ": " << cpp_strerror(r)
          << std::endl;                                                     
       }                                                                    
     }                                                                      
   } else {                                                                 
     m_fd = -1;                                                             
   }                                                                                                        
}

先看fd是否有效,否則,就創建m_log_file, m_log_file就是具體的log路徑及文件名。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章