2018年10月31日 星期三

CentOS 7 變更預設 run-level

CentOS 7 變更預設 run-level

CentOS 7 變更 runlevel

不同的執行等級(runlevel)在開機時會進入不同的操作介面,在CentOS 6以前的版本,如下表所示有七個等級:

Runlevel target 意義
0 runlevel0.target, poweroff.target 關閉系統
1 runlevel1.target, rescue.target 單人模式,僅允許root登入,不執行服務
2 runlevel2.target 多人模式,不執行服務
3 runlevel3.target, multi-user.target 多人模式,不包含圖形介面
4 runlevel4.target 用戶自訂
5 runlevel5.target 圖形模式
6 runlevel6.target 重新啟動

在CentOS 6以前的版本中,想要修改該runlevel執行的服務時,會修改/etc/rc<runlevel>.d目錄下的內容,依照相應的規則進行命名,在開機時會載入相應的服務;要切換到該執行等級,可直接輸入指令init <runlevel>;修改開機時預設的啟動等級,則是修改/etc/inittab檔案。

CentOS 7不使用init來管理服務,而是用systemd管理。切換執行等級使用systemctl isolate <target>進行切換;要新增開機啟動的服務則是將服務寫入/etc/systemd/system/資料夾中(或/usr/lib/systemd/system);修改開機時預設的等級,則是systemctl set-default <target>

2018年10月11日 星期四

matplotlib note

matplotlib note

簡單理解matplitlib layout

matplotlib 圖示

上圖是matplotlib中常用的幾個物件。Figurematplotlib.figure.Figure物件,可看做整個畫布;Axes是matplotlib.axes.Axes物件,實際上會把資料畫在Axes上頭。

簡單的繪圖是直接使用matplotlib.pyplot.plot()。此方法會隱式的建立一個Figure,將其設定為current Figure,在此Figure下隱式的建立一個matplotlib.axes._subplots.Axes(一種Axes),最後把數據繪製在該Axes上,並回傳Line物件。

這樣的方法使用上相當簡單,但由於FigureAxes物件都是被隱式的建立,當具有多個Axes與多個Figure時,需要使用plt.get_fignumsplt.gcfplt.gca等方法進行切換,管理上變得相當複雜。

稍微複雜,但可以明確觀察物件的方始是手動新增FigureAxes,並存成變數加以管理。實際的程式碼如下 :

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0, 100, 0.1)-50
y = x**3

fig = plt.figure()
axes = fig.add_axes((0.1, 0.1, 0.8, 0.8))
lines = axes.plot(x, y)
fig.show()

在上頭的範例中,add_axes函數的第一個參數是axes的(左邊界位置, 下邊界位置, 寬度, 高度),其單位是fig中長寬的比例。

藉由此方法,可以在單一程式中明確的建立多個Figure物件,並在單一Figure下建立多個Axes子圖。以下是簡單的範例:

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0, 100, 0.1)-50
y = x**3

fig = plt.figure()
fig.add_axes((0.1, 0.1, 0.8, 0.8))
fig = plt.figure()
main_axes = fig.add_axes((0.1, 0.1, 0.8, 0.8))
main_lines = main_axes.plot(x, y)
sub_axes = fig.add_axes((0.2, 0.6, 0.15, 0.15))
main_lines = sub_axes.plot(x, y)

用物件的方式管理Figure執行起來明確得多。例如要刪除線段時,可以用line.remove(),學習上也較一般的方法明確得多。

2018年10月5日 星期五

logging 日誌

logging 日誌

logging

logging是用來記錄(logging)事件的模組。logging的主要用途是把希望印出的訊息依據嚴重程度切分數個等級,並將格式化後的訊息輸出至檔案或標準輸出、標準錯誤。由於logging將輸出訊息切分得很細緻,且具有很好的靈活度,因此在程式正式上線時常用來取代printstdoutstderr等輸出方式。

承上段,logging將輸出依照事件的嚴重性切分,當輸出等級高於指定的閥值時,則輸出訊息;若事件等級低於指定的閥值時,則不輸出訊息。預設的等級以及其對應的數值如下表:

等級 數值 輸出函數
CRITICAL 50 logging.critical
ERROR 40 logging.error
WARNING 30 logging.warning
INFO 20 logging.info
DEBUG 10 logging.debug

設定logging等級最簡單的使用方式是藉由logging.basicConfig函數設定輸出的格式以及等級:

import logging

logging.basicConfig(level=logging.INFO)
logging.info('This will get logged')
logging.debug('This will not get logged')

輸出 :

INFO:root:This will get logged

其中rootroot logger的意思。如果想將訊息同時輸出至不同的檔案或stream中,則需要藉由logging.getLogger函數新增其他的logger。除此之外,logging.basicConfig也可以設定輸出的格式、輸出的檔案等等。相關需求可以參考官方文件。

Reference

  1. Python documentation
  2. Real python

2018年10月3日 星期三

Watchdog 監控系統文件

Watchdog 監控系統文件

Written with StackEdit.

watchdog是用於監控檔案事件的Python API庫。受監控的檔案事件常見的有四種,分別為:移動、新增、移除、修改。當watchdog偵測到這四個事件時,會呼叫相應的函數進行反應。

下面是官方網站上提供的範例:

import sys
import time
import logging
from watchdog.observers import Observer
from watchdog.events import LoggingEventHandler

if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO,
                        format='%(asctime)s - %(message)s',
                        datefmt='%Y-%m-%d %H:%M:%S')
    path = sys.argv[1] if len(sys.argv) > 1 else '.'
    event_handler = LoggingEventHandler()
    observer = Observer()
    observer.schedule(event_handler, path, recursive=True)
    observer.start()
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()

watchdog的運作流程是observer開啟一個線程對檔案系統進行監控,當偵測到檔案事件時,將事件的旗標傳入event_handler,由event_handler進行反應。

在上面的範例中,由LoggingEventHandler作為event_handler。由LoggingEventHandler的原碼可以看到,它繼承自FileSystemEventHandler,並重載了FileSystemEventHandleron_movedon_createdon_deletedon_modified四個方法,並使用logging庫進行等級為INFO的記錄。

class LoggingEventHandler(FileSystemEventHandler):
    """Logs all the events captured."""

    def on_moved(self, event):
        super(LoggingEventHandler, self).on_moved(event)

        what = 'directory' if event.is_directory else 'file'
        logging.info("Moved %s: from %s to %s", what, event.src_path,
                     event.dest_path)

    def on_created(self, event):
        super(LoggingEventHandler, self).on_created(event)

        what = 'directory' if event.is_directory else 'file'
        logging.info("Created %s: %s", what, event.src_path)

    def on_deleted(self, event):
        super(LoggingEventHandler, self).on_deleted(event)

        what = 'directory' if event.is_directory else 'file'
        logging.info("Deleted %s: %s", what, event.src_path)

    def on_modified(self, event):
        super(LoggingEventHandler, self).on_modified(event)

        what = 'directory' if event.is_directory else 'file'
        logging.info("Modified %s: %s", what, event.src_path)

我們可以按照同樣的邏輯撰寫自己的event_handler

class MyEventHandler(FileSystemEventHandler):
    """Logs all the events captured."""

    def on_created(self, event):
        super(LoggingEventHandler, self).on_created(event)

        what = 'directory' if event.is_directory else 'file'
        logging.warning("Created %s: %s by ", what, event.src_path)

這樣就變更為在WARING層級才會記錄新增事件,其他類別的事件都不處理。

除此之外,也可以進行其他處置,例如發現有目錄下有新增檔案後(如圖片),呼叫其他程式對其進行壓縮等等…

Reference

Watchdog
Watchdog github

2018年10月2日 星期二

MySQL Note

MySQL Note

MySQL 筆記

連結資料庫(使用cli)

官方提供的cli:

shell> mysql -u <username> -p

使用mycli

shell> mycli -u <username>

常用資料庫操作

新增資料庫

create database <database name>;

移除資料庫

drop database <database name>;

使用資料庫

use <database name>;

顯示所有資料庫

show database;

修改密碼

ALTER USER <name>@<host> IDENTIFIED BY <new_password>;

常用資料表操作

新增、移除、修改資料表:

新增資料表

CREATE TABLE cats
(
  id              INT unsigned NOT NULL AUTO_INCREMENT, # Unique ID for the record
  name            VARCHAR(150) NOT NULL,                # Name of the cat
  owner           VARCHAR(150) NOT NULL,                # Owner of the cat
  birth           DATE NOT NULL,                        # Birthday of the cat
  PRIMARY KEY     (id)                                  # Make the id the primary key
);

相關資料型別

移除資料表:

drop table <table_name> rename 

修改資料表:

alter table <table_name> add <column_name> <data_type>;
alter table <table_name> drop <column_name> <data_type>;

修改資料表名:

alter table <old_table_name> rename to <new_table_name>;
rename table <old_table_name> to <new_table_name>;

顯示目前使用的資料庫中所有的資料表:

SHOW TABLES;

columns相關操作

顯示全部的columns

describe <table_name>;

顯示單一column

describe <table_name> <column_name>;

修改column名

alter table <table_name> rename column <old_column_name> to <new_column_name>;

修改column資料型別

alter table <table_name> modlty <column_name> <new_datatype>;

資料操作

選取資料表中全部的資料

select * from <table_name>;

按照條件選取

select * from <table_name> where <condition>;

例:

select name from comics where id==123;
select * from comics where title is NULL;

移除特定資料:

delete from <table_name> where <condition>;

插入資料(輸入的值須符合型別)

insert into <table_name> (column_name1, column_name2,...,) values (data1, data2....);

修改資料

update <table_name>
set <column_name1>=<new_value1>,
    <column_name2>=<new_value2>
where <condition>

從.sql file匯入

source <path_of_sqlfile>

外鍵(FOREIGN KEY

FOREIGN KEY (<local_table_column>) REFERENCES <foreign_table> (<foreign_table_primary_key_name>)

Reference

  1. Getting Started with MySQL
  2. MySQL 8.0 Reference Manual
  3. SQL語法教學