Jex’s Note

S.M.A.R.T 相關指令

介紹

可以檢測你的硬碟健康狀態

Installation

sudo apt-get install smartmontools

當硬碟不支援時顯示 Unavailable :

jex@jex-VirtualBox [stp:1] { /var/www  }$ sudo smartctl -i /dev/sda1
smartctl 5.43 2012-06-30 r3573 [x86_64-linux-3.8.0-19-generic] (local build)
Copyright (C) 2002-12 by Bruce Allen, http://smartmontools.sourceforge.net

=== START OF INFORMATION SECTION ===
Device Model:     VBOX HARDDISK
Serial Number:    VB47e46d42-bbe471de
Firmware Version: 1.0
User Capacity:    8,589,934,592 bytes [8.58 GB]
Sector Size:      512 bytes logical/physical
Device is:        Not in smartctl database [for details use: -P showall]
ATA Version is:   6
ATA Standard is:  ATA/ATAPI-6 published, ANSI INCITS 361-2002
Local Time is:    Fri May 17 10:08:11 2013 CST
SMART support is: Unavailable - device lacks SMART capability.

To check if the device has SMART capability:

己打開會顯示:

jex_lin@jex { ~  }$ sudo smartctl -i /dev/sda1
smartctl 6.1 2013-03-16 r3800 [x86_64-linux-3.7.4-1-ARCH] (local build)
Copyright (C) 2002-13, Bruce Allen, Christian Franke, www.smartmontools.org

=== START OF INFORMATION SECTION ===
Model Family:     Western Digital RE3 Serial ATA
Device Model:     WDC WD5002ABYS-18B1B0
Serial Number:    WD-WCASY6863830
LU WWN Device Id: 5 0014ee 2ade88ff2
Add. Product Id:  DELL▒
Firmware Version: 02.03B04
User Capacity:    500,107,862,016 bytes [500 GB]
Sector Size:      512 bytes logical/physical
Rotation Rate:    7200 rpm
Device is:        In smartctl database [for details use: -P show]
ATA Version is:   ATA8-ACS (minor revision not indicated)
SATA Version is:  SATA 2.5, 3.0 Gb/s
Local Time is:    Mon May 13 13:51:20 2013 CST
SMART support is: Available - device has SMART capability.
SMART support is: Enabled

沒打開smart會顯示 Disabled:

jex_lin@jex { /usr/sbin  }$ sudo smartctl -i /dev/sda1
smartctl 6.1 2013-03-16 r3800 [x86_64-linux-3.7.4-1-ARCH] (local build)
Copyright (C) 2002-13, Bruce Allen, Christian Franke, www.smartmontools.org

=== START OF INFORMATION SECTION ===
Model Family:     Western Digital RE3 Serial ATA
Device Model:     WDC WD5002ABYS-18B1B0
Serial Number:    WD-WCASY6863830
LU WWN Device Id: 5 0014ee 2ade88ff2
Add. Product Id:  DELL▒
Firmware Version: 02.03B04
User Capacity:    500,107,862,016 bytes [500 GB]
Sector Size:      512 bytes logical/physical
Rotation Rate:    7200 rpm
Device is:        In smartctl database [for details use: -P show]
ATA Version is:   ATA8-ACS (minor revision not indicated)
SATA Version is:  SATA 2.5, 3.0 Gb/s
Local Time is:    Mon May 13 16:04:42 2013 CST
SMART support is: Available - device has SMART capability.
SMART support is: Disabled

If SMART is not enabled, it can be enabled by doing:

打開:

jex_lin@jex { ~  }$ sudo smartctl -s on /dev/sda1
smartctl 6.1 2013-03-16 r3800 [x86_64-linux-3.7.4-1-ARCH] (local build)
Copyright (C) 2002-13, Bruce Allen, Christian Franke, www.smartmontools.org

=== START OF ENABLE/DISABLE COMMANDS SECTION ===
SMART Enabled.

沒打開:

jex_lin@jex { /usr/sbin  }$ sudo smartctl -s off /dev/sda1
smartctl 6.1 2013-03-16 r3800 [x86_64-linux-3.7.4-1-ARCH] (local build)
Copyright (C) 2002-13, Bruce Allen, Christian Franke, www.smartmontools.org

=== START OF ENABLE/DISABLE COMMANDS SECTION ===
SMART Disabled. Use option -s with argument 'on' to enable it.

check device

jex_lin@jex { ~/jex (master) }$ sudo smartctl -P show /dev/sda
smartctl 5.43 2012-06-30 r3573 [x86_64-linux-3.8.0-25-generic] (local build)
Copyright (C) 2002-12 by Bruce Allen, http://smartmontools.sourceforge.net

ATA device successfully opened

Use 'smartctl -a' (or '-x') to print SMART (and more) information

Test the device health :

  1. Short (runs tests that have a high probability of detecting device problems)
  2. Extended (or Long; a short check with complete disk surface examination)
  3. Conveyance (identifies if damage incurred during transportation of the device)

To view the device’s available tests and the time it will take to perform each test do:

打開:

jex_lin@jex { ~  }$ sudo smartctl -c /dev/sda1
smartctl 6.1 2013-03-16 r3800 [x86_64-linux-3.7.4-1-ARCH] (local build)
Copyright (C) 2002-13, Bruce Allen, Christian Franke, www.smartmontools.org

=== START OF READ SMART DATA SECTION ===
General SMART Values:
Offline data collection status:  (0x85) Offline data collection activity
                                        was aborted by an interrupting command from host.
                                        Auto Offline Data Collection: Enabled.
Self-test execution status:      ( 248) Self-test routine in progress...
                                        80% of test remaining.
Total time to complete Offline
data collection:                ( 9480) seconds.
Offline data collection
capabilities:                    (0x7b) SMART execute Offline immediate.
                                        Auto Offline data collection on/off support.
                                        Suspend Offline collection upon new
                                        command.
                                        Offline surface scan supported.
                                        Self-test supported.
                                        Conveyance Self-test supported.
                                        Selective Self-test supported.
SMART capabilities:            (0x0003) Saves SMART data before entering
                                        power-saving mode.
                                        Supports SMART auto save timer.
Error logging capability:        (0x01) Error logging supported.
                                        General Purpose Logging supported.
Short self-test routine
recommended polling time:        (   2) minutes.
Extended self-test routine
recommended polling time:        ( 112) minutes.
Conveyance self-test routine
recommended polling time:        (   5) minutes.
SCT capabilities:              (0x303f) SCT Status supported.
                                        SCT Error Recovery Control supported.
                                        SCT Feature Control supported.
                                        SCT Data Table supported.

沒打開會顯示SMART Disabled:

jex_lin@jex { /usr/sbin  }$ sudo smartctl -c /dev/sda1
smartctl 6.1 2013-03-16 r3800 [x86_64-linux-3.7.4-1-ARCH] (local build)
Copyright (C) 2002-13, Bruce Allen, Christian Franke, www.smartmontools.org
SMART Disabled. Use option -s with argument 'on' to enable it.
(override with '-T permissive' option)

To run the tests do:

smartctl -t short /dev/<device>
smartctl -t long /dev/<device>
smartctl -t conveyance /dev/<device>

Results

To view the test’s overall health status (compiled from all tests):

jex_lin@jex { ~  }$ sudo smartctl -H /dev/sda1
smartctl 6.1 2013-03-16 r3800 [x86_64-linux-3.7.4-1-ARCH] (local build)
Copyright (C) 2002-13, Bruce Allen, Christian Franke, www.smartmontools.org

=== START OF READ SMART DATA SECTION ===
SMART overall-health self-assessment test result: PASSED

PASSED表示硬碟健康狀態良好 Failure表示硬碟有問題

To view the test’s result errors:

jex_lin@jex { ~  }$ sudo smartctl -l selftest /dev/sda1
smartctl 6.1 2013-03-16 r3800 [x86_64-linux-3.7.4-1-ARCH] (local build)
Copyright (C) 2002-13, Bruce Allen, Christian Franke, www.smartmontools.org

=== START OF READ SMART DATA SECTION ===
SMART Self-test log structure revision number 1
Num  Test_Description    Status                  Remaining  LifeTime(hours)  LBA_of_first_error
1  Extended offline    Completed without error       00%        95         -
2  Short offline       Completed without error       00%        94         -

To view the test’s detailed results:

sudo smartctl -a /dev/sda1

或使用↓顯示部份資訊

sudo smartctl -A /dev/sda1

If no errors are reported the device is likely healthy. If there are a few errors this may or may not indicate a problem and should be investigated further. When a device starts to fail it is recommended to backup the data and replace it.

ID#

  • This ID for the attribute is displayed as a decimal number in this report but other reports may display it in its native hexadecimal format.

Attribute Name

  • The human readable description of the ID#

Flag

  • This is a hexadecimal description of the purposes of this attribute combined so they can be represented by a number.
  • For example is it for performance, error rates or pre-fail or some combination of these and others.

Value

  • This is a normalized version of the data that starts at its best possible value (like 200 for this attribute) and then decreases as it gets worse (now 192 for this attribute).

Worst

  • The worst that the Value has ever been.
  • Note that some vendors firmware may actually increase the “Worst” value for some rate-type Attributes.

Threshold (THRESH)

  • These are defined by the vendor.
  • The threshold for the Value. Once the Value goes below this, the drive will consider it to be FAILED for this attribute and depending on the attribute (like this one) the whole drive will be considered to be failing and warnings will be sent to backup and replace it.

Type

  • A human readable version of the Flag value but not as detailed.
  • Note that if an Attribute is of type ‘Pre-fail’, it does not mean that your disk is about to fail! It only has this meaning if the Attribute’s current Normalized value is less than or equal to the threshold value.

Updated

  • How often the attribute’s value is updated.
  • Some SMART attributes values, that are updated only during off-line data collection activities are labeled “Offline” in column “UPDATED”.

When Failed

  • If there was a failure where the value reached or went below the threshold value, the power-on lifetime is displayed here (usually in hours )
  • If the Attribute’s current “Normalized value” is less than or equal to the threshold value, then the attribute is marked with “FAILING_NOW” in column WHEN_FAILED.

Raw Value

  • The raw non-normalized value of the attribute.
  • Please keep in mind that the conversion from RAW value to a quantity with physical units is not specified by the SMART standard! smartctl only reports the different Attribute types, values, and thresholds as read from the device. It does not carry out the conversion between “Raw” and “Normalized” values: this is done by the disk’s firmware.
  • In most cases, the values printed by smartctl are sensible. For example the temperature Attribute generally has its raw value equal to the temperature in Celsius. However in some cases vendors use unusual conventions. For example the Hitachi disk on my laptop reports its power-on hours in minutes, not hours. Some IBM disks track three temperatures rather than one, in their raw values. Have a look at our wiki pages on topic SMART attributes.

狀態:

  • Worst = 曾經發生過最壞時的值
  • Value = 目前的值
  • Threshold = 門檻值,超過此值代表硬碟瑕疵已超過容許的範圍
  • T.E.C. = 一個預估你的硬碟壽命的日期

補充:

參數說明:

  • -h 顯示參數說明及範例
  • -V 顯示版本等相關資訊
  • -i 顯示該硬碟的相關資訊(包括是否啟動 SMART)
  • -a 顯示硬碟所有相關資訊
  • -H 顯示硬碟 SMART 健康狀況 (健康 PASSED、生病 FAILED)
  • -c 顯示硬碟支援的檢查、測試項目
  • -A 顯示硬碟檢查後的相關屬性值 (例如 194 Temperature_Celsius 最後值為 HDD 溫度)
  • -l TYPE 顯示硬碟檢查後 Log (TYPE: error, selftest, selective, directory)
  • -t TEST 執行硬碟測試 (TEST: offline, short, long, conveyance, select,M-N pending,N afterselect,on afterselect,off)
  • -X 放棄執行硬碟測試

中斷背景檢測硬碟:

jex_lin@jex { ~  }$ sudo smartctl -X /dev/sda1
smartctl 6.1 2013-03-16 r3800 [x86_64-linux-3.7.4-1-ARCH] (local build)
Copyright (C) 2002-13, Bruce Allen, Christian Franke, www.smartmontools.org

=== START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION ===
Sending command: "Abort SMART off-line mode self-test routine".
Self-testing aborted!

顯示硬碟錯誤log:

jex_lin@jex { ~  }$ smartctl -l error /dev/sda1
smartctl 6.1 2013-03-16 r3800 [x86_64-linux-3.7.4-1-ARCH] (local build)
Copyright (C) 2002-13, Bruce Allen, Christian Franke, www.smartmontools.org
Smartctl open device: /dev/sda1 failed: Permission denied
jex_lin@jex { ~  }$ sudo smartctl -l error /dev/sda1
smartctl 6.1 2013-03-16 r3800 [x86_64-linux-3.7.4-1-ARCH] (local build)
Copyright (C) 2002-13, Bruce Allen, Christian Franke, www.smartmontools.org

=== START OF READ SMART DATA SECTION ===
SMART Error Log Version: 1
No Errors Logged

-d指定設備類型,例如: ata, scsi, marvell, sat, 3ware,N

$ smartctl -s on -d ata /dev/sdb

disk判斷項目 :

假設 exec() 第3參數為 $is_fail

  1. 有安裝但不支援,$is_fail = 0 (解析第2參數判斷Unavailable)
  2. 有安裝但沒打開,$is_fail = 0 (解析第2參數判斷Disabled)
  3. 沒安裝smart,$is_fail = 1
  4. disk路徑亂打(/devx/sda8),$is_fail = 1 or 127
  5. 指定不存在的disk (/dev/sda8),$is_fail = 2

參考來源:

https://sites.google.com/site/lab586/linuxnote/hddchecktip https://wiki.archlinux.org/index.php/SMART http://space.itpub.net/12823785/viewspace-504042 http://www.weithenn.org/cgi-bin/wiki.pl?Smartmontools-%E6%AA%A2%E6%9F%A5%E6%B8%AC%E8%A9%A6%E7%A1%AC%E7%A2%9F%E5%A3%BD%E5%91%BD http://southdogs.blogspot.tw/2008/05/smart.html http://www.adminii.com/486.html http://html5.litten.com/accessing-and-assessing-a-hard-drives-s-m-a-r-t-data/ http://sourceforge.net/apps/trac/smartmontools/wiki/Howto_ReadSmartctlReports_ATA

PHP - Exec() 執行系統指令

介紹

exec() 是用來執行 linux 指令的,並且可以透過它取得執行結果

分析 exec('ls -l 2>&1', $result, $is_fail)

[1] 首先第一個參數是 command line,執行的是ls -l指令

[2] 第二個參數是當執行成功才會有值,失敗則不會有值

原本執行錯誤時 $result 是不會有值的,但當 command line 加上2>&1就可以將錯誤訊息回傳給 $result

[3] 第三個參數為狀態碼,簡單來說就是執行成功為 0,非 0 則是失敗

  • 1 : Catchall for general errors
  • 2 : Misuse of shell builtins (according to Bash documentation)
  • 126 : Command invoked cannot execute
  • 127 : “command not found”
  • 128 : Invalid argument to exit

不要完全相信以上表的錯誤訊息, 建議要取得準確的錯誤訊息還是加上2>&1比較好

exec(‘sudo …..’), 使用 sudo 執行指令

[1] apache 預設執行身份在 /etc/apache2/envvars

export APACHE_RUN_USER=www-data
export APACHE_RUN_GROUP=www-data

[2] 原本是在 /etc/apache2/apache2.conf :

有些 linux 的 apache 的預設執行身份不像 ubuntu 是用變數,而是直接寫死在這的, 所以 ubuntu 的 apache2.conf 會再去 load envvars,取得 user 身份 :

User ${APACHE_RUN_USER}
Group ${APACHE_RUN_GROUP}

[3] 執行權限設定在 /etc/sudoers , apache 預設的 http user 是 www-data

如果要用 sudoexec 執行特定指令

www-data ALL=(ALL) NOPASSWD: /usr/sbin/smartctl,/usr/bin/php

允許執行所有指令:

www-data ALL=(ALL) NOPASSWD:ALL

為了讓 exec() 執行 sudo 時不需要輸入密碼,否則 exec() 沒辦法執行

[4] 例如執行 smartctl 指令:

echo exec("sudo -u www-data sudo smartctl -i /dev/sda1");

如果 apache 預設的執行 user 是 www-data (例如: 步驟 1 預設執行 user 是 www-data),則可以省略寫成:

echo exec("sudo smartctl -i /dev/sda1");

參考來源:

Dd 指令

(最後更新: 2016-04-14)

介紹

用來複製或轉換為一個檔案

假設目前系統環境只有一顆硬碟,當初安裝時沒有多切,但不想要重新再切,所以以dd產生一個檔案,並且利用這個檔案所佔的空間去模擬一個磁碟

[1] 產生一個50M的檔案

sudo dd if=/dev/sda1 of=~/virtual2.img bs=1M count=50

[2] 將這個檔案切成磁碟

cfdisk virtual2.img

選logical

[3] 格式化成XFS

sudo mkfs.xfs virtual2.img -f

[4] mount它,-o pquota是xfs特有的參數不需理會,可以將xfs改成你熟悉的ext4

sudo mount -t xfs ~/virtual2.img ./test -o pquota

xfs的 folder quota 正常:)

swap 指令

  • 通常安裝主機都會設定 swap
  • 但如果沒有 swap 或要增加 swap 可自行設定

sudo swapon -a

sudo swapoff -a

釋放 swap

sudo swapoff -a
sudo swapon -a

查看 swap 狀態

swapon -s

另種方式看 Swap 的狀態

$ free -m
             total       used       free     shared    buffers     cached
Mem:           992        711        281          0         83        418
-/+ buffers/cache:        209        782
Swap:            0          0          0

建立/增加 swap

建立 1G swap

sudo dd if=/dev/zero of=/swapfile bs=1M count=1024

掛載這個 Swap

sudo mkswap /swapfile
sudo swapon /swapfile

Swap 確實設定好了

swapon -s
Filename                                Type            Size    Used    Priority
/dev/xvdb                               partition       262140  133804  -1
/swapfile                               file            1048572 0       -2


$ free -m
             total       used       free     shared    buffers     cached
Mem:           992        896         95          0         18        660
-/+ buffers/cache:        217        775
Swap:         1023          0       1023

確寶每一次 swap 都會被啟動

/etc/fstab :

/swapfile   none         swap    sw      0       0

為了避免太差的效能, swappiness 應該設定 10, 可以讓 swap 作為緊急緩衝區, 預防用光記憶體導致 crash

echo 10 | sudo tee /proc/sys/vm/swappiness
echo vm.swappiness = 10 | sudo tee -a /etc/sysctl.conf

設定正確權限給 swap file

sudo chown root:root /swapfile
sudo chmod 0600 /swapfile

ref : https://www.digitalocean.com/community/tutorials/how-to-add-swap-on-ubuntu-12-04

Vim 快捷鍵

Command Line

  • vim http://www.google.com : 開啟google原始碼
  • vim -p qq.php cc.php : 用tabe顯示,用gt切換下一個tabe
  • vim -O qq.php cc.php : 垂直分割顯示
  • vim -o qq.php cc.php : 水平分割顯示
  • vim -u NONE cc.php : 不要進行初始化直接開啟檔案 (對開大檔會快很多)

新增、刪除、插入

  • O : 在游標那行的上一行插入新的一行
  • o : 在游標那行的下一行插入新的一行
  • I : 在該行的第一個字元進入插入模式
  • i : 在游標前進入插入模式
  • A ( = $ + a) : 在該行的最後一個字元進入插入模式
  • a : 在游標後進入插入模式
  • C : 刪除游標後的字串並進入到insert模式
  • cc : 刪除該行並進入到insert模式(保留縮排)
  • 1cj : 刪除游標該行及下一行共2行並進入插入模式
  • D : 刪除游標後的字串
  • dd : 刪除整行
  • 2dd : 刪除下列2行
  • 10dh : 向左刪除10個字元
  • d0 : 刪除游標位置前的字元
  • d^ : 刪除游標位置前的字元(保留縮排)
  • d$ : 刪除游標位置到最後一個字元
  • de : 刪除游標位置到區塊的最後一個字元
  • db : 向前刪除區塊單字
  • dw : 向後刪除區塊單字
  • x : 刪除游標所在的字元
  • X : 向前刪除字元
  • s : 刪除游標那個字元並進入 insert 模式
  • S : 同 cc
  • 10x : 刪除游標後的5個字元
  • J : 將游標所在列與下一列的資料結合成同一列
  • 3J : 將下兩行包含游標該行共3行合併成一行
  • d0 : 游標所在處向前刪除到第0格
  • d^ : 游標所在處向前刪除到縮排處停止
  • diw : 刪除游標上的單字
  • ciw : 刪除游標上的單字並進入insert模式
  • cw : 刪除在單字上游標以後字串
  • ci' : 刪除單引號內的字串並進入insert模式
  • ci" : 刪除雙引號內的字串並進入insert模式
  • ci( : 刪除括號內的內容並進入insert模式
  • ci[ : 刪除中括號內的內容並進入insert模式
  • ci{ : 刪除大括號內的內容並進入insert模式
  • ci< : 刪除<(內容)>並進入insert模式
  • ca' : 刪除單引號內的字串及單引號並進入 insert 模式
  • di' : 刪除單引號內的字串
  • dst : 刪除 html 標籤, 但內容會保留
  • dit : 刪除 html 標籤內容, 但標籤會保留
  • cit : 刪除 html 標籤內容, 並進入 insert 模式
  • 6i6a + 任意字串 : 6 次 * 任意字串
  • d/a : 刪到 a 為止
  • guu : 整行變小寫
  • gUU : 整行變大寫
  • g~~ : 整行大小寫交換

複製、剪下、貼上

  • shift + Insert : (insert模式下)將系統剪貼簿貼上游標位置。
  • ctrl + v : 對區塊共同做編輯
  • ctrl + v 選取後按c : 把選取的字刪掉並進入insert模式
  • V(select whole line) + y : 相當於 ctrl + c
  • v(select area) + y : 相當於 ctrl + c
  • P : 貼上於目前游標的上一行
  • p : 貼上於目前游標的下一行,相對於 ctrl + v
  • y1G : 複製游標所在列到第一列的所有資料
  • y0 : 複製游標所在的那個字元到該行行首的所有資料
  • y$ : 複製游標所在的那個字元到該行行尾的所有資料
  • yy : 複製游標所在的那一行
  • 20yy : 複製 20 行
  • Y : 複製游標所在的那一行
  • :m+ : 把目前這一行往下移動一行
  • :m-2 : 把目前這一行往上移動一行
  • shift + insert : 在insert模式貼上滑鼠複製的東西
  • [p : 貼到游標前
  • ]p : 貼到游標後
  • dip : 刪除最外層的tag及裡面的所有內容
  • yiw : 複製單字
  • yi' : 複製單引號內的字串
  • vi' : 選取單引號內的字串並進入visual模式
  • " + a + y + i + ' : 將單引號的內容(不包含單引號)存進暫存a
  • " + a + y + a + ' : 將單引號的內容(包含單引號)存進暫存a
  • v + ^ + y : 複製從游標到最前面的字串
  • vitp : 貼在 HTML Tag 裡
  • :2y : copy 第 2 行
  • :2,7y : copy 第 2 ~ 7 行

Visual模式

  • ~ : 在visual模式已選取下,切換大 / 小寫
  • U : 在visual模式已選取下,轉成大寫
  • u : 在visual模式已選取下,轉成小寫
  • viw : 選取游標上的單字並進入visual模式。(v = visual, i = inside, w = word)
  • vit : 選取<tag>裡面的內容並進入visual模式。例: <a href='#'>(選取這一塊)</a>
  • vat : 選取<tab>全部內容包含<tag>本身,並進入visual模式(a = around)。選取<a ..(略)..>內容</a>整段
  • vip : 選取最外層的tag及裡面的所有內容並進入visual模式
  • ggVG : 全選
  • = : 在visual模式己選取下,自動縮排

游標移動

  • # : 向前搜尋游標上相同的單字。或按N 往下 n 往上
  • * : 向後搜尋游標上相同的單字
  • % : 在() {} 上會切換到相對應的上
  • [ + { : 在括號裡游標會移到 {
  • ] + } : 在括號裡游標會移到 }
  • [ + ( : 在括號裡游標會移到 (
  • ] + ) : 在括號裡游標會移到 )
  • 0 : 游標移到最前
  • ^ : 游標移到最前(保留縮排)
  • $ : 標移到最後
  • :1212G: 游標移到第12行
  • H : 移動到該頁第一行
  • M : 移動到該頁中間那一行
  • L : 移動到該頁最後一行
  • 1Ggg : 移動到檔案的第一行
  • G : 移動到檔案的最後一行
  • w : 移動到下一個單字, 2w 移到下兩個單字
  • W : 跳下一個單字比w更遠
  • b : 移動到前一個單字、與w相反
  • e : 移動到目前單字的最後一個字
  • t + a : 找到 a 的前一格
  • fa : 往下移動找到 a 。按;移到下一個
  • Fa : 往上找到 a 。按;移到下一個
  • 3fa : 移動到往後的第三個a的位置
  • 4j : 往下移動4行
  • 4k : 往上移動4行
  • 4h : 往左移動4格
  • 4l : 往右移動4格
  • ctrl + o : 回覆到上一個游標的位置(按太多會到你上一個編輯的檔案)
  • ( : 跳到上一個區塊的第一行或最後一行
  • ) : 跳到下一個區塊的第一行或最後一行
  • [[ : 跳到上一個區塊的第一行
  • ]] : 跳到下一個區塊的第一行
  • { : 跳到上一個區塊的最後一行
  • } : 跳到下一個區塊的最後一行
  • + : 移動到非空白區的下一列(保留縮排)
  • - : 移動到非空白區的上一列(保留縮排)
  • mx : 記下目前的為止為 x
  • 'x : 回到 x 這個位置
  • '' : 回到最後的 jump點
  • ctrl + i : 回到後一個 jump 點
  • ctrl + o : 回到前一個 jump 點

畫面移動

  • ctrl + f : 下一頁 ( = Page Up)
  • ctrl + b : 上一頁 ( = Page Down)
  • ctrl + d : 下半頁
  • ctrl + u : 上半頁
  • ctrl + y : 畫面移上一行
  • ctrl + e : 畫面移下一行
  • zz : 移動畫面置中游標
  • zb : 移動畫面置底游標
  • zt : 移動畫面置頂游標
  • zl : 畫面向右水平移動一格
  • zL : 畫面向右水平移動半個畫面
  • zh : 畫面向左水平移動一格
  • zH : 畫面向左水平移動半個畫面
  • zs : 根據目前的游標位置將畫面水平移動到最左
  • ze : 根據目前的游標位置將畫面水平移動到最右

在分割視窗時讓其他視窗一起 scrolling down

對每個視窗下 :set scb (:set scrollbind 縮寫), 然候再測試是否 work (ctrl + e)

取消的話對其中一個下 :set scb! (:set noscrollbind 縮寫) 就可以解除了

搜尋、取代

  • /abc : 向下搜尋abc
  • ?abc : 向上搜尋abc
  • n : 下一筆搜尋結果
  • N : 上一筆搜尋結果
  • :35,44g/uid/ : 在 33 到 44 行之間搜尋 uid
  • :100,200s/vbird/VBIRD/g : 在 100 到 200 行之間搜尋 vbird 並取代為 VBIRD
  • :1,$s/word1/word2/g : 從第一行到最後一行尋找 word1 字串,並將該字串取代為 word2
  • :1,$s/word1/word2/gc : 且在取代前顯示提示字元給使用者確認 (confirm) 是否需要取代
  • :%s/phpindo/phpinfo/g : 取代。%s = 1,$s
  • :101,201s/phpindo/phpinfo/g : 取代 101~201 行
  • gd : 在程式的變數上循序按下 gd,可以找到 local declaration 的位置
  • gD : 同上,只是會找到 global declaration 的位置

分割視窗

  • :new : 開新的水平分割視窗
  • :vnew : 開新的垂直分割視窗
  • :sp : 新增目前的檔案到新視窗
  • :sp t1.php : 新增另一個檔案加入到分割視窗
  • vs : 同vsp
  • :vsp : 垂直分割
  • :sp ./ : 用選取的方式尋找檔案
  • :q : 離開
  • shift + ZZ : 離開; 等同 :q
  • ctrl + ww : 切換到下一個視窗
  • ctrl + w + 3w : 切換到第三個視窗(如果有多個視窗)
  • ctrl + w + p : 切換到前一個視窗
  • ctrl + w + n : 開啟新視窗
  • ctrl + w + w : 游標切到不同的視窗 (不管是水平還是垂直)
  • ctrl + w + q : 結束目前視窗
  • ctrl + w + x : 視窗交換位置
  • :sq + 按space + (按)tab + :列出可選的選項,按↓進入資料夾
  • ctrl + w + v : 垂直
  • ctrl + w + s : 水平
  • ctrl + w + o : 留下目前視窗關閉其他
  • ctrl + w + (jkhl) : 切換下、上、左、右
  • ctrl + w + (+-) : 調整垂直大小
  • ctrl + w + (<>) : 調整水平大小
  • ctrl + w + _ : 將視窗垂直打開到最大
  • ctrl + w + |(pipe) : 將視窗水平打開到最大
  • ctrl + w + = : 將其他視窗復原大小

暫存器

  • :reg : 把暫存器裡的東西叫出來看
  • "2y : 複製到暫存器索引2 (可配合visual模式使用)
  • "kyy : 複製整行到索引k
  • "kp : 貼上索引k
  • :let @k='' : 清空索引k
  • :let @0=@1 : 索引1複製給索引0
  • "+x : 剪下,將資料放進剪貼簿及vim緩衝區
  • "+y : 複製,將資料放進剪貼簿及vim緩衝區
  • "+gp : 貼上

buffer

  • :e qq.php : 跳去編輯 qq.php 這個檔案, qq.php 會在 buffer 裡
  • :ls : 顯示buffer裡的檔案
  • :bn : 切到下一個buffer檔案
  • :bp : 切到上一個buffer檔案
  • :b2 : 切到buffer 2號檔案
  • :b qq.php : 切到檔名為qq.php的buffer檔案
  • ctrl + 6 : 回到上一個開的buffer檔案。注意 : :bp是不一樣的!

tab

  • :h tabe : 列出tabe的helper
  • gt : 跳到下一個tabe
  • gT : 跳到上一個tabe
  • :tab ba : 將目前的buffer切換成tab
  • :tabe : 開一個新的tab
  • :tabe qq.php : 開啟qq.php為tab(不存在就會在當前目錄建立新檔案)
  • :tabmove 1 : 將當前 tabe 順序移動到順序1
  • 3gt : 跳至tabe順序3

儲存、離開

  • :wa : 全部儲存
  • :qa : 關掉全部視窗
  • :w : 儲存
  • :q : 離開
  • :w! : 強制儲存
  • :wq : 儲存後離開
  • :w ~/qq.php : 另存新檔
  • :e qq.php : 打開qq.php,並關閉目前所在頁面

其他操作

  • u : 回復上一個動作
  • ctrl + r : 回復下一個動作
  • :noh : 取消選取的highlight
  • :! ls -l : 在 vim 下暫時切到外面執行 ls -l
  • :set nu : 顯示行號,設定之後會在每一行的最前面顯示行號
  • :set nonu : 與 set nu 相反,為取消行號!
  • :set paste : paste模式,直接貼上文字時格式不會跑掉
  • :set tabstop=4 : 設定一個tab等於四個空白長度
  • :set expandtab : 設定以後,使用tab鍵時會用空白取代(由tabstop設定而定)
  • :set incsearch : / 不需按 Enter, 邊打邊搜尋
  • :set nohlsearch : / 不要 highlight 找到的字串
  • :retab : 將tab轉換成space
  • :edit or :edit! : reload
  • ctrl + p : 自動補齊變數名稱或語法
  • ~ : 可以將游標上的字切換大 / 小寫
  • . : 重覆前一個動作
  • >> : 縮排
  • 3>> : 游標那行與下2行一起縮排
  • << : 縮排倒退
  • :3,5>> : 3到5行向右縮排2次
  • :3,5< : 3到5行向左縮排1次
  • :%norm A* : 在每一行最後面加上 *norm = type the following commands
  • :11,13 norm Aqq : 在第 11~13 行最後面加上 qq 字串
  • gf : 跳到 source code 的檔案, 例如在 /tmp/cc.ff 上按, 就會跳到該檔案
  • ctrl + w + gf : 會在 tab 打開 source code 的檔案
  • :指令 + ctrl + d : 會出現相關指令的 menu, 再按 tab 會補齊指令

範圍

加上註解(//)

  • 加上註解 :
    1. 在第一行按下ctrl + v 進入到選取區塊模式
    2. 游標向下移到要註解的最後一行
    3. I
    4. 輸入 // (註解符號,看你的程式語言是什麼)
    5. esc
  • 取消註解 :
    1. 在第一行按下ctrl + v 進入到選取區塊模式
    2. 游標向下移到要註解的最後一行
    3. 按一個右鍵, 讓區塊把 // 包起來
    4. x刪除

  • 加上註解 : :34,37s/^/\/\//g
  • 取消註解 : :34,37s/^\/\///g

範圍縮排

shift + v : 選出要縮排的列再按>>,這時候只會縮排一次,再按.(複製上一個動作)就可以要縮排幾次就按幾下

vim plugin

hello.vim

function! XX()
    echo getpos(".")
endfunction

隨便編輯其他文件

  1. :source hello.vim
  2. :call XX()

就會 print 出你目前的游標位子了, 如: [0, 3, 8, 0]

get external command return

let a = system('ls -al')
echo a

讓 vim 複製到 Clipboard

確認目前 vim 版本有支援此功能

(TODO: 未完成)

vim --version | grep clipboard

如果看到 +clipboard or +xterm_clipboard 就表示有

看到 -clipboard and -xterm_clipboard 表示沒有

:set clipboard=unnamed
:set clipboard+=unnamed

查看檔案的 binary hex

command:

vim test.txt

test.txt 進入後輸入 :%!xxd

0000000: 3031 3233 3435 3637 3839 4142 4344 4546  0123456789ABCDEF
0000010: 4748 494a 4b4c 4d4e 4f50 5152 5354 5556  GHIJKLMNOPQRSTUV
0000020: 5758 595a 0a                             WXYZ.

最後面的 0a 是換行字元

編輯中間的 hex

0000000: 3031 3233 3435 3637 3839 4142 4344 4546  0123456789ABCDEF

將 23 (hex 3233) 位置調換成 32 (hex 3332)

0000000: 3031 3332 3435 3637 3839 4142 4344 4546  0123456789ABCDEF

再執行 :%!xxd -r 將 hex 轉回來

0132456789ABCDEFGHIJKLMNOPQRSTUVWXYZ

XFS - Folder Quota

介紹

xfs 是一種 file system 的 format, 像 ext4 一樣, 不過它特別的地方在於它可以方便的對目錄做 quota 限制

Ubuntu 安裝 :

sudo apt-get install xfsprogs xfsdump

Set quota :

Make the filesystem and mount it:

mount /dev/sda5 /mnt/xfs -o pquota

Create a project named “project1”, which is the “/mnt/xfs/test1” tree:

mkdir test1     #on /mnt/xfs
echo "11:/mnt/xfs/test1" >> /etc/projects
echo "project1:11" >> /etc/projid
xfs_quota -x -c "project -s project1" /dev/sda5

Set the tree quota to 2 MB:

xfs_quota -x -c "limit -p bsoft=1m bhard=2m project1" /dev/sda5

或直接指定project id

xfs_quota -x -c "limit -p bsoft=1m bhard=2m 1" /dev/sda5

也可以使用projects id指定 ex : “limit -p bsoft=1m bhard=2m 11”

That’s it.. Now let’s make some tests:

dd if=/dev/zero of=/mnt/xfs/test1/aaa count=10 bs=1024k

And there’s also a nice report! (looks nicer with a fixed-width console font)

xfs_quota -x -c "report /dev/sda5"

將一個quota綁定多個資料夾:

在/etc/projects設定:

7:/jex_ugc/jexstorage/default/jex_lin
7:/jex_ugc/jexstorage/default/hun

xfs report 中 id=7 的 used欄位會將jex_lin及hun資料夾使用空間加總,超過quota限制的話就會將兩個資料夾鎖住

Set Unlimited Quota

sudo xfs_quota -x -c "limit -p bsoft=0m bhard=0m project1" /dev/mapper/jex--vg-jex--lv

Remove quota :

執行清除project quota指令

$ sudo xfs_quota -xc "project -C 1" /dev/mapper/jex--vg-jex--lv
Clearing project 1 (path /jex_ugc/jexstorage/test)...
Processed 1 (/etc/projects and cmdline) paths for project 1 with recursion depth infinite (-1).

刪除資料夾與 /etc/projects 及 /etc/projid 的對應資料

  • 如果要將/etc/projects其中一個project id的資料夾做更改一定要先執行clear quota再改,不然如果舊的資料夾還存在的話會變成限制成兩個資料夾
  • 要先執行clear quota再刪除資料夾否則會發生找不到資料夾的錯誤

      jex@jex:/jex_ugc/jexstorage$ sudo xfs_quota -xc "project -C 1" /dev/mapper/jex--vg-jex--lv
      xfs_quota: cannot find mount point for path `/jex_ugc/jexstorage/test': No such file or directory
      Processed 0 (/etc/projects and cmdline) paths for project 1 with recursion depth infinite (-1).
    

其他功能:

To suspend (i.e. freeze) an XFS file system, use:

xfs_freeze -f /mount/point

To unfreeze an XFS file system, use:

xfs_freeze -u /mount/point

command :

  • -c cmd xfs_quota commands may be run interactively (the default) or as arguments on the command line. Multiple -c arguments may be given. The commands are run in the sequence given, then the program exits.
  • -p prog Set the program name for prompts and some error messages, the default value is xfs_quota.
  • -x Enable expert mode. All of the administrative commands (see the ADMINISTRATOR COMMANDS section below) which allow modifi - cations to the quota system are available only in expert mode.
  • -d project Project names or numeric identifiers may be specified with this option, which restricts the output of the individual xfs_quota commands to the set of projects specified. Multiple
  • -d arguments may be given.

Command details :

xfs_quota> jex@jex:/jex_ugc/jexstorage/test$ sudo xfs_quota -x
xfs_quota> ?
df [-bir] [-hn] [-f file] -- show free and used counts for blocks and inodes
disable [-gpu] [-v] -- disable quota enforcement
dump [-gpu] [-f file] -- dump quota information for backup utilities
enable [-gpu] [-v] -- enable quota enforcement
help [command] -- help for one or all commands
limit [-gpu] bsoft|bhard|isoft|ihard|rtbsoft|rtbhard=N -d|id|name -- modify quota limits
off [-gpu] [-v] -- permanently switch quota off for a path
path [N] -- set current path, or show the list of paths
print -- list known mount points and projects
project [-c|-s|-C|-d <depth>|-p <path>] project ... -- check, setup or clear project quota trees
quit -- exit the program
quot [-bir] [-gpu] [-acv] [-f file] -- summarize filesystem ownership
quota [-bir] [-gpu] [-hnNv] [-f file] [id|name]... -- show usage and limits
remove [-gpu] [-v] -- remove quota extents from a filesystem
report [-bir] [-gpu] [-ahnt] [-f file] -- report filesystem quota information
restore [-gpu] [-f file] -- restore quota limits from a backup file
state [-gpu] [-a] [-v] [-f file] -- get overall quota state information
timer [-bir] [-gpu] value -d|id|name -- get/set quota enforcement timeouts
warn [-bir] [-gpu] value -d|id|name -- get/set enforcement warning counter

Use 'help commandname' for extended help.

測試紀錄

測試刪除資料夾再新增回來同樣的名稱,quota限制是否還在?

將test資料夾刪除,這時看report,會有之前設定的記錄(只要projects及projid沒刪除,都會顯示project{id}的狀態)

Project ID       Used       Soft       Hard    Warn/Grace
---------- --------------------------------------------------
project1            0       1024       2048     00 [--------]

新增test資料夾

複製10m的檔案,不受quota 2m的影響

jex@jex:/jex_ugc/jexstorage$ dd if=/dev/zero of=/jex_ugc/jexstorage/test/aaa count=10 bs=1024k
10+0 records in
10+0 records out
10485760 bytes (10 MB) copied, 0.00780022 s, 1.3 GB/s

report顯示的Used也不正常 (其實是10m但report那還是顯示0)

jex@jex:/jex_ugc/jexstorage$ du
10240   ./test
10240   .
jex@jex:/jex_ugc/jexstorage$ sudo xfs_quota -xc "report /dev/mapper/jex--vg-jex--lv"
Project quota on /jex_ugc/jexstorage (/dev/mapper/jex--vg-jex--lv)
                               Blocks
Project ID       Used       Soft       Hard    Warn/Grace
---------- --------------------------------------------------
project1            0       1024       2048     00 [--------]

解決方法: 重新將test與project{id}綁定,再觀察report結果,Used那正常顯示

jex@jex:/jex_ugc/jexstorage$ sudo xfs_quota -xc "project -s project1" /dev/mapper/jex--vg-jex--lv
Setting up project project1 (path /jex_ugc/jexstorage/test)...
Processed 1 (/etc/projects and cmdline) paths for project project1 with recursion depth infinite (-1).
jex@jex:/jex_ugc/jexstorage$ sudo xfs_quota -xc "report /dev/mapper/jex--vg-jex--lv"
Project quota on /jex_ugc/jexstorage (/dev/mapper/jex--vg-jex--lv)
                               Blocks
Project ID       Used       Soft       Hard    Warn/Grace
---------- --------------------------------------------------
project1        10240       1024       2048     00 [--none--]

再copy 10m進去,quota就把它擋掉了,得到預期結果

jex@jex:/jex_ugc/jexstorage$ dd if=/dev/zero of=/jex_ugc/jexstorage/test/bbb count=10 bs=1024k
dd: opening /jex_ugc/jexstorage/test/bbb: Disk quota exceeded

就一個已存在的project id指向到一個新建立的資料夾(abc),會發生什麼情形?

2:/jex_ugc/jexstorage/default/test

改成:

2:/jex_ugc/jexstorage/default/abc
  • 綁定後再設quota, 在report顯示出來的used其實是舊的資料夾加上新的資料夾的使用容量,如果超過使用容量就會變成兩個都鎖

解決辦法: XFS在將路徑與project id做綁定時,極大的可能是以inode做綁定,所以只要有綁定都會記錄在xfs資料庫中,所以即使將/etc/projects刪除,但只要曾經綁過就會被紀錄下來,而將quota限制在同一個project id曾綁定過所有資料夾使用的總合

  • 最好的做法是在將/etc/projects變更前先將舊資料夾做Clear Quota,讓舊資料夾跟project id沒有關係後,再變更/etc/projects及將新資料夾與project id綁定
  • 或者是直接刪除該舊資料夾讓xfs找不到它的inode,但可能潛在如果後來生成的資料夾被指派到一樣的indoe,造成xfs也對他做quota 限制

在一個有設定quota的資料夾下將檔案搬移出的問題

假設資料夾 a 有設定quota,project id 為 8 (以下簡稱 p8),裡面有一個檔案test.txt 它的 inode 為 1130

[情況1]

將 a 的 test.txt 檔案搬移到 未設定 quota 的資料夾 b,會產生問題是 p8 仍然還是指向 inode 1130,如果將 a 的 quota 給註銷掉換成資料夾 c,則 p8 的新主人雖然是資料夾 c ,但查看 report 會發現 used 那邊會出錯,因為 inode 1130 這個檔案的使用量會被算到資料夾 c (實際上檔案是在 b 那邊) ,解決方法只要把 inode 1130 的檔案刪除

[情況2]

將 a 的 test.txt 檔案搬移到 已設定 quota 的資料夾 b,就不會發生 p8 指向 inode 錯亂的問題了,因為搬過去時 inode也變重新指派

用 inode 反查

sudo xfs_db -xr -c 'inode 16777350' -c p /dev/sda5

http://xfs.org/docs/xfsdocs-xml-dev/XFS_User_Guide/tmp/en-US/html/ch08s16.html

備註 :

  • 現代的文件系統如JFS和XFS能夠動態地增加inode,因此不會用盡inode。(From: inode wiki)
  • 動態變更上限值 : 直接執行步驟3重新指定上限值即可
  • 步驟2 “11:/mnt/xfs/test1”中的編號11只可以使用數字,並且 不能超過65535 ,超始值 : 1
  • 當資料夾rename時,/etc/projects更改路徑,原有的quota限制也都會對應到
  • About soft and hard : When a user exceeds the soft limit, the timer is enabled. Any time the quota drops below the soft limits, the timer is disabled. If the timer pops, the particular limit that has been exceeded is treated as if the hard limit has been reached, and no more resources are allocated to the user. The only way to reset this condition, short of turning off limit enforcement or increasing the limit, is to reduce usage below quota. Only the superuser (i.e. a sufficiently capable process) can set the time limits and this is done on a per filesystem basis.
  • 中文檔名:

    1. Max. filename length : 255bytes
    2. 85個中文 => OK!
    3. 80個中文+15英文 => OK!
    4. 80個中文+15數字 => OK!
    5. 80個中文+16個英文或數字 => error!
  • 符號:

    1. 允許符號 : ~!@#$%^&*()_+ \‘ ”
    2. 除了 / 不允許其他都OK

其他限制方式:

User Limits

limits xfs_quota -x -c 'limit bsoft=1000m bhard=1200m username'
limits xfs_quota -x -c 'limit isoft=500 ihard=700 username'

Group Limits.

xfs_quota -x -c 'limit -g bsoft=1000m bhard=1200m groupname'
Project Limits

參考:

http://xfs.org/docs/xfsdocs-xml-dev/XFS_User_Guide/tmp/en-US/html/index.html http://www.held.org.il/blog/2008/07/per-directory-quota-not-a-dream/ http://dell9.ma.utexas.edu/cgi-bin/man-cgi?xfs_quota+8 http://docs.fedoraproject.org/en-US/Fedora/14/html/Storage_Administration_Guide/xfsfreeze.html

磁碟分割、掛載

fdisk

  • -l : 查閱目前系統所有的partition有哪些
  • -l /dev/sda1 : 確認一下它是否可以分割
  • /dev/sda1 : 輸入h可以查閱可使用的指令

磁碟分割

當安裝linux,要分割磁碟時,類型有分為兩種:

  1. primary : 放置主要系統檔
  2. logical : 如果要自行利用磁區可以選擇它

假設磁碟共有80G,但不想全部都給主要系統檔,可以選擇:

  • 分 20G 給 primary
  • 分 25G 給 logical
  • 分 25G 給 logical
  • 建議將“記憶體”的2倍分給swap

這樣就有兩個25G磁碟可以讓你任意掛載運用, 但要注意分割磁碟時預設會mount, 要記得設定不要mount

掛/卸載磁碟

1) 在 /home/user_me 建立 test1 及 test2, 資料夾

2) 查詢磁碟狀態

# 列出有磁碟
fdisk -l

# 顯示己掛載之磁碟
df -l

# 顯示filesystem type
df -T

3) 掛載

mount /dev/sda5 /home/user_me/test1
mount /dev/sda6 /home/user_me/test2

如果test1資料夾裡有資料, 在掛載後, 只會顯示/dev/sda5磁碟的資料, 但只要卸載/dev/sda5,原本test1資料就會回來了

如果partition出現錯誤不能掛載: Partition 2 does not start on physical sector boundary.

解法方法 : 刪除 partition -> 再建立 partition -> format 要的檔案格式

4) 卸載:

umount /home/user_me/test1    #卸載/dev/sda5
umount /home/user_me/test2    #卸載/dev/sda6

重新開機後自動 mount

/etc/fstab :

以空格為區塊各代表:
[磁碟裝置檔名或該裝置的 Label] [掛載點] [磁碟分割槽的檔案系統] [檔案系統參數] [能否被 dump 備份指令作用] [是否以 fsck 檢驗磁區 (0:不檢驗, 1:最早檢驗, 2: 要檢驗)]

/dev/sda5 /home/user_me/test1 xfs pquota 0 2
/dev/sda5 /home/user_me/test1 ext4

刪除partition

sudo fdisk /dev/sda
Command (m for help): d
Partition number (1-6): 2
Command (m for help): w (存檔後重開機)

建立partition

extend:

sudo fdisk /dev/sda
Command (m for help): n

第一次切要先選extend(按enter按到底), 第二次之後再切才能選logic

logical

Command (m for help): n
Command (m for help): w (存檔後重開機)

format partition

sudo cfdisk /dev/sda5

> 選logical, 指定完大小後選write

format to xfs

sudo mkfs.xfs /dev/sda5 -f

Mac 系統格式化

mac 系統原生就有 disk utility 可以做格式化, 在 spotlight 搜尋就可以開啟了

在左側選取要格式化的 usb 或硬碟,在右側再選取想要格式化的檔案格式

如果要格式化成 FAT32 請選擇 MS-DOS (FAT)

檔案格式

如果檔案系統需要同時支援 window, mac 建議格式化為 FAT32

FAT32

  • 支援 windows, mac
  • 單檔最大 4GB
  • 最大容量 2TB
  • 較容易 disk errosr
  • 效率稍差

exFAT

  • 支援 windows, mac, linux
  • 單檔最大 4GB
  • 最大容量 2TB

NTFS (windows only)

  • windows 原生支援
  • 在 mac 上只能讀
  • 最大單檔 16TB
  • 最大容量 256TB

HFS+

  • mac 原生支援
  • Required for Time Machine
  • 最大單檔 8EiB
  • 最大容量 8EiB

Inode

在linux下,一個檔案產生後,會有一個inode,可以用來當作這個檔案的編號。 假設有一個檔案叫做cc.txt,它的inode編號為135, 當我用mv移動到不管哪個資料夾下,它的inode編號依然會是135, 但當使用cp複製它時,它的inode編號就會重新指派了。

查看inode

ls -i
7042739 README.md       6954370 bashrc          2287673 bin

用 inode 找 file / folder

find ~/conf -inum 2287673
/Users/jex/conf/bin

Crontab 排程

[1] 建立/var/www/test/hello.sh 檔:

#!/bin/bash
echo "Hello World"

[2] 假使要每一分鐘執行一次hello.sh

執行:

$ crontab -e

會進入編輯器,輸入:

# 每分鐘執行一次
*/1 * * * * echo "job every minute" >> /tmp/tz

# 每 0:15, 12:15 分執行一次
15 0,12 * * * /bin/bash -l -c 'cd /var/www/web_app && RAILS_ENV=development bundle exec rake schedule:check_something --silent'

# 星期一~五  9am~18pm
00 09-18 * * 1-5 /home/ramesh/bin/check-db-status

格式 : 分(0-59), 時(0-23) ,日(1-31) ,月(1-12) ,週(0-6), Command

[3] 其他指令 :

執行排程並不會影響到你目前工作視窗,因為它是背景執行的,所以每隔一分鐘, 並不會看到 “Hello World” 字串出現在畫面上,但它會在每一次執行時紀錄在log裡

編輯 crontab 的工作內容,若要移除某些排程,直接刪除就可以了

crontab -e

查詢 crontab 的工作內容

crontab -l

移除所有的 crontab 的工作內容

crontab -r

查看 crontab

grep CRON /var/log/syslog

運作指令:

service crond start         # 啟動服務
service crond stop          # 關閉服務
service crond restart       # 重啟服務
service crond reload        # 重新載入配置

或
/etc/init.d/cron restart

Set Timezone

注意!! : 如果修改完主機的 timezone 卻沒有重新啟動 cron, 那麼 cron 仍然還會是吃舊的 timezone

參考此篇修改 timezone後要記得 restart : sudo service crond restart

另一種方式設定排程

除了crontab -e可以設定每日排程外,也有另一種方法執行排程

系統預設提供這些時間點的排程,在etc/的cron.daily/ cron.hourly/ cron.monthly/ cron.weekly/

只需要把script丟進你想要的時間的資料夾裡,系統時間到就會自動執行

而各時段執行排程的時間點設定在/etc/crontab

# m h dom mon dow user  command
=====================================

# /etc/cron.hourly,目錄下的腳本會每個小時讓執行一次,在每小時的17分鐘時運行;
17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly

# /etc/cron.daily,目錄下的腳本會每天讓執行一次,在每天的6點25分時運行;
25 6    * * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )

#  /etc/cron.weekly,目錄下的腳本會每週讓執行一次,在每週第七天的6點47分時運行;
47 6    * * 7   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )

# /etc/cron.mouthly,目錄下的腳本會每月讓執行一次,在每月1號的6點52分時運行;
52 6    1 * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )

run cron.daily

/etc/cron.daily 底下至少要有r-x權限

sudo chmod 755 your_cron

測試看哪一個沒有執行

run-parts --test --report /etc/cron.daily

強制重啟cron:

ps aux | grep cron
root     15082  0.0  0.0  18708  1068 ?        Ss   13:23   0:00 cron

kill 15082
ps aux | grep cron # 若已經自動跑起來, 就不需要下面的步驟
/usr/sbin/cron &

另一種方法

/etc/cron.d/ 底下建立新檔案

每天 01:05 刪除超過 15 天以上的 log, logs/以下的子資料夾裡的檔案也會清

5 1 * * * ec2-user /usr/bin/find /home/apps/php-api/app/logs/* -mtime +15 -exec rm {} \;

不用重啟 cron 就會生效了

ref

使用grb(git_remote_branch)實例操作

安裝

gem install git_remote_branch

[1] 在github開一個 practice_grb.git

[2] 使用grb create 在 practice_grb.git 建立一個遠端 master

隨便建立一個資料夾並且初始化

jex_lin@devm3 { ~/public_html  }$ mkdir test
jex_lin@devm3 { ~/public_html  }$ cd test
jex_lin@devm3 { ~/public_html/test  }$ git init
Initialized empty Git repository in /home/jex_lin/public_html/test/.git/

增加remote

jex_lin@devm3 { ~/public_html/test  }$ git remote add origin git@github.com:jex-lin/practice_grb.git

因為資料夾才剛初始化完,如果執行grb create master會出現error

jex_lin@devm3 { ~/public_html/test  }$ grb create master
git_remote_branch version 0.3.6

git push origin :refs/heads/master
remote: warning: Deleting a non-existent ref.
To git@github.com:jex-lin/practice_grb.git
 - [deleted]         master

git fetch origin

git branch --track master origin/master
fatal: Not a valid object name: 'origin/master'.

git checkout master
error: pathspec 'master' did not match any file(s) known to git.

所以要先新增一筆資料並且add、commit

jex_lin@devm3 { ~/public_html/test  }$ vim test
jex_lin@devm3 { ~/public_html/test  }$ git add test
jex_lin@devm3 { ~/public_html/test  }$ git commit -m "I am master v1.0"
[master (root-commit) c39ac4a] I am master v1.0
 1 file changed, 1 insertion(+)
 create mode 100644 test

再一次建立遠端主機的master。建立完後可以到github看到master這個主線了

jex_lin@devm3 { ~/public_html/test (master) }$ grb create master
git_remote_branch version 0.3.6

git push origin master:refs/heads/master
Counting objects: 3, done.
Writing objects: 100% (3/3), 226 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@github.com:jex-lin/practice_grb.git
 * [new branch]      master -> master

git fetch origin

git branch --track master origin/master
fatal: A branch named 'master' already exists.

git checkout master
Already on 'master'

[3] 模擬另一個開發者(test2)

jex_lin@devm3 { ~/public_html  }$ mkdir test2
jex_lin@devm3 { ~/public_html  }$ cd test2
jex_lin@devm3 { ~/public_html/test2  }$ git init
Initialized empty Git repository in /home/jex_lin/public_html/test2/.git/
jex_lin@devm3 { ~/public_html/test2  }$ git remote add origin git@github.com:jex-lin/practice_grb.git

將遠端主機的master pull下來

jex_lin@devm3 { ~/public_html/test2  }$ git pull origin master
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 3 (delta 0)
Unpacking objects: 100% (3/3), done.
From github.com:jex-lin/practice_grb
 * branch            master     -> FETCH_HEAD

修改檔案、add、commit

jex_lin@devm3 { ~/public_html/test2 (master) }$ vim test
jex_lin@devm3 { ~/public_html/test2 (master) }$ git add test
jex_lin@devm3 { ~/public_html/test2 (master) }$ git commit -m "I am test, master v2.0"
[master c2d0b59] I am test, master v2.0
 1 file changed, 1 insertion(+)

push 到github的master

jex_lin@devm3 { ~/public_html/test2 (master) }$ git push
Counting objects: 5, done.
Writing objects: 100% (3/3), 271 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@github.com:jex-lin/practice_grb.git
   c39ac4a..c2d0b59  master -> master

就會看到 github 上就會有新的commit了

當然也可以在遠端建立develop分支

jex_lin@devm3 { ~/public_html/test2 (master) }$ grb create develop
git_remote_branch version 0.3.6

git push origin master:refs/heads/develop
Total 0 (delta 0), reused 0 (delta 0)
To git@github.com:jex-lin/practice_grb.git
 * [new branch]      master -> develop

git fetch origin

git branch --track develop origin/develop

git checkout develop
Switched to branch 'develop'

修改檔案、add、commit

jex_lin@devm3 { ~/public_html/test2 (develop) }$ vim test
jex_lin@devm3 { ~/public_html/test2 (develop) }$ git add test
jex_lin@devm3 { ~/public_html/test2 (develop) }$ git commit -m "I am test2, develop v1.0"
[develop 43d1ca6] I am test2, develop v1.0
 1 file changed, 1 insertion(+)

push到github的develop

jex_lin@devm3 { ~/public_html/test2 (develop) }$ git push
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 289 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@github.com:jex-lin/practice_grb.git
   c2d0b59..43d1ca6  develop -> develop

在github會看到develop就會多一個commit了

查看test2的遠端分支

jex_lin@devm3 { ~/public_html/test2 (develop) }$ git branch -r
  origin/develop
  origin/master

回test查看的遠端分支

jex_lin@devm3 { ~/public_html/test2 (develop) }$ cd ..
jex_lin@devm3 { ~/public_html  }$ cd test
jex_lin@devm3 { ~/public_html/test (master) }$ git branch -r
  origin/master

可以發現到test2比test多了develop分支

[4] 將develop分支加入到test

jex_lin@devm3 { ~/public_html/test (master) }$ grb track develop
git_remote_branch version 0.3.6

git fetch origin
remote: Counting objects: 8, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 6 (delta 0), reused 6 (delta 0)
Unpacking objects: 100% (6/6), done.
From github.com:jex-lin/practice_grb
 * [new branch]      develop    -> origin/develop
   c39ac4a..c2d0b59  master     -> origin/master

git branch --set-upstream develop origin/develop
The --set-upstream flag is deprecated and will be removed. Consider using --track or --set-upstream-to

再查看test的遠端分支就有develop了

jex_lin@devm3 { ~/public_html/test (master) }$ git branch -r
  origin/develop
  origin/master

[5] 疑難排解

發現如果在test2修改並且push,切回test時pull失敗

jex_lin@devm3 { ~/public_html/test (master) }$ git pull
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details

    git pull <remote> <branch>

If you wish to set tracking information for this branch you can do so with:

    git branch --set-upstream-to=origin/<branch> master

解法: 重新將本機的master與遠端的master綁定,就可以pull了

jex_lin@devm3 { ~/public_html/test (master) }$ git branch --set-upstream-to=origin/master master
Branch master set up to track remote branch master from origin.
jex_lin@devm3 { ~/public_html/test (master) }$ git pull
Updating c39ac4a..4375ac9
Fast-forward
 qq   | 1 +
 test | 2 ++
 2 files changed, 3 insertions(+)
 create mode 100644 qq

develop 也是一樣的情況,步驟一樣,先綁定遠端的develop,再pull

jex_lin@devm3 { ~/public_html/test (develop) }$ git branch --set-upstream-to=origin/develop develop
Branch develop set up to track remote branch develop from origin.
jex_lin@devm3 { ~/public_html/test (develop) }$ git pull
Updating 43d1ca6..c625ce4
Fast-forward
 test | 1 +
 1 file changed, 1 insertion(+)

PHP - 練習抽像、介面

程式碼 :

header('Content-Type: text/html; charset=utf-8');

/**
 * 題目 :
 *      (1)有一台紅色休旅車跟藍色法拉利
 *      (2)有前進、後退、左轉、右轉,基本功能
 *      (3)有加速跟減速,法拉利性能較優異(法拉利加速跟減速單位都是20公里, 休旅車是10公里)
 *      (4)紅色休旅車是自排,極速是180公里(打檔的方法我省略它沒有做)
 *      (5)藍色法拉利是手排,極速是320公里
 *
 * 介面跟抽象的差異 :
 *      (1)介面不可以定義屬性,只可以定義方法,而且只能是public,否則會得到錯誤,
 *          如: "Fatal error: Access type for interface method Car::accelerate() must be omitted in"
 *      (2)抽象可以宣告public/protected/private方法及屬性
 *      (3)只要有一個方法宣告為abstract,類別就要宣告為abstract
 *      (4)抽象跟類別都不能實體化,代表著 :
 *          1. 抽象只能被繼承(一個類別只能繼承一個父類別)
 *          2. 介面只能被實作(一個類別可以實作很多介面)
 *
 * 做法 :
 *      (1)如果大家都會做一模一樣的事情,可以用抽象定義
 *          (例如 : 因為前進、後退、左轉、右轉,動作大家都是一樣所以我在抽象定義)
 *      (2)如果大家是做同一件事情,但做法有差異用介面定義
 *          (例如 : 加速跟減速因為車種的性能不一樣,所以我在介面定義)
 *      (3)封裝速度,設定上下限
 */


// 介面 - 車子
interface Car {

    public function accelerate($times);     // 加速
    public function decelerate($times);     // 減速
}

// 抽像 - 操作動作
abstract class Operate {

    public $name;
    public $color;
    protected $_transmission;   // 排檔(手、自排)
    private $_direction;        // 方向(左、右轉)
    private $_movement;         // 移動(前、後)
    abstract protected function _set_speed($speed);
    abstract public function get_speed();

    public function __construct()
    {
        echo "$this->name [$this->color] [$this->_transmission] 生產出來了! <br>";
    }

    /**
     * 前進
     *
     * @access  public
     * @return  null
     */
    public function move_forward()
    {
        $this->_movement = '前進';
        echo $this->name."前進了! <br>";
    }

    /**
     * 後退
     *
     * @access  public
     * @return  null
     */
    public function move_back()
    {
        $this->_movement = '後退';
        echo $this->name."後退了! <br>";
    }

    /**
     * 左轉
     *
     * @access  public
     * @return  null
     */
    public function turn_left()
    {
        $this->_direction = '左轉';
        echo $this->name."左轉了! <br>";
    }

    /**
     * 右轉
     *
     * @access  public
     * @return  null
     */
    public function turn_right()
    {
        $this->_direction = '右轉';
        echo $this->name."右轉了! <br>";
    }

    /**
     * 取得車子目前狀態
     *
     * @access  public
     * @return  null
     */
    public function get_status()
    {
        echo $this->name."目前狀態是 : $this->_movement $this->_direction";
    }
}

// 物件 - 休旅車
class Suv extends Operate implements Car {

    public $name = '<span style="color:red;">休旅車</span>';
    public $color = '紅';
    protected $_transmission = '自排';
    private $_speed = 0;

    /**
     * set速度變數(極速180)
     *
     * @access  protected
     * @param   int
     * @return  null
     */
    protected function _set_speed($speed)
    {
        $this->_speed += $speed;
        if ($this->_speed >= 180)
        {
            $this->_speed = 180;
        }
        elseif ($this->_speed <= 0)
        {
            $this->_speed = 0;
        }
    }

    /**
     * get速度變數
     *
     * @access  public
     * @return  int
     */
    public function get_speed()
    {
        echo ",目前時速是 : ".$this->_speed." km/h <br>";
        return $this->_speed;
    }

    /**
     * 加速
     *
     * @access  public
     * @param   int         $times 加速的次數
     * @return  null
     */
    public function accelerate($times = 1)
    {
        $this->_set_speed(10 * $times);
        echo $this->name."加速".(10 * $times)." km/h,目前時速是 : $this->_speed<br>";
    }

    /**
     * 減速
     *
     * @access  public
     * @param   int         $times 減速次數
     * @return  null
     */
    public function decelerate($times = 1)
    {
        $this->_set_speed(-10 * $times);
        echo $this->name."減速".(-10 * $times)." km/h,目前時速是 : $this->_speed<br>";
    }
}

// 物件 - 法拉利
class Ferrari extends Operate implements Car {

    public $name = '<span style="color:blue;">法拉利</span>';
    public $color = '藍';
    protected $_transmission = '手排';
    private $_speed = 0;

    /**
     * set速度變數(極速320)
     *
     * @access  protected
     * @param   int
     * @return  null
     */
    protected function _set_speed($speed)
    {
        $this->_speed += $speed;
        if ($this->_speed >= 320)
        {
            $this->_speed = 320;
        }
        elseif ($this->_speed <= 0)
        {
            $this->_speed = 0;
        }
    }

    /**
     * get速度變數
     *
     * @access  public
     * @return  int
     */
    public function get_speed()
    {
        echo ",目前時速是 : ".$this->_speed." km/h <br>";
        return $this->_speed;
    }

    /**
     * 加速
     *
     * @access  public
     * @param   int         $times 加速的次數
     * @return  null
     */
    public function accelerate($times = 1)     // 法拉利性能好, 所以加20
    {
        $this->_set_speed(20 * $times);
        echo $this->name."加速".(20 * $times)." km/h,目前時速是 : $this->_speed<br>";
    }

    /**
     * 減速
     *
     * @access  public
     * @param   int         $times 減速次數
     * @return  null
     */
    public function decelerate($times = 1)     // 法拉利性能好, 所以減20
    {
        $this->_set_speed(-20 * $times);
        echo $this->name."減速".(-20 * $times)." km/h,目前時速是 : $this->_speed<br>";
    }
}


// 建立物件
$ferrari = new Ferrari();
$suv = new Suv();

// 執行動作
$ferrari->move_back();
$suv->move_back();
$ferrari->accelerate(5);
$ferrari->accelerate();
$ferrari->move_forward();
$suv->accelerate(3);
$ferrari->decelerate(30);
$suv->decelerate(5);
$ferrari->turn_left();
$suv->turn_right();
$suv->accelerate(20);
$ferrari->accelerate(20);
$suv->decelerate();
$ferrari->decelerate(4);
$suv->decelerate(8);
$suv->turn_left();
$ferrari->turn_right();

// 顯示最後結果
$suv->get_status().$suv->get_speed();
$ferrari->get_status().$ferrari->get_speed();

結果 :

擷取.PNG