tmp目錄
首先看下FHS的定義。
FHS(Filessystem Hierarchy Standard) 的重點在於規范每個特定的目錄下應該要放置什么樣子的數據。
tmp約定的存放內容
/tmp 這是讓一般用戶或者正在執行的程序暫時放置文件的地方。這個目錄是任何人都能夠訪問,所以你需要定期清理一下。當然,重要數據不可放置在此目錄。因為FHS甚至建議在開機時,應該要將/tmp下的數據都刪除
清理方式
不同的 Linux 發行版其實對 /tmp 目錄的清理方式有所不同:
· 在 Debian-like 的系統,啟動的時候才會清理 (規則定義在 /etc/default/rcS )
· 在 RedHat-like 的系統,按文件存在時間定時清理 (RHEL6 規則定義在 /etc/cron.daily/tmpwatch ; RHEL7 以及 RedHat-like with systemd 規則定義在 /usr/lib/tmpfiles.d/tmp.conf , 通過 systemd-tmpfiles-clean.service 服務調用)
· 在 CentOS 里,也是按文件存在時間清理的 (通過 crontab 的配置 /etc/cron.daily 定時執行 tmpwatch 來實現)
· 在 Gentoo 里也是啟動清理,規則定義在 /etc/conf.d/bootmisc
tmpwatch
例子
flags=-umc /usr/sbin/tmpwatch "$flags" -x /tmp/.X11-unix -x /tmp/.XIM-unix \ -x /tmp/.font-unix -x /tmp/.ICE-unix -x /tmp/.Test-unix \ -X ‘/tmp/hsperfdata_*’ 10d /tmp
語法
-u, --atime 基於訪問時間來刪除文件,默認的。
-m, --mtime 基於修改時間來刪除文件。
-c, --ctime 基於創建時間來刪除文件,對於目錄,基於mtime。
-M, --dirmtime 刪除目錄基於目錄的修改時間而不是訪問時間。
-a, --all 刪除所有的文件類型,不只是普通文件,符號鏈接和目錄。
-d, --nodirs 不嘗試刪除目錄,即使是空目錄。
-d, --nosymlinks 不嘗試刪除符號鏈接。
-f, --force 強制刪除。
-q, --quiet 只報告錯誤信息。
-s, --fuser 如果文件已經是打開狀態在刪除前,嘗試使用“定影”命令。默認不啟用。
-t, --test 僅作測試,並不真的刪除文件或目錄。
-U, --exclude-user=user 不刪除屬於誰的文件。
-v, --verbose 打印詳細信息。
-x, --exclude=path 排除路徑,如果路徑是一個目錄,它包含的所有文件被排除了。如果路徑不存在,它必須是一個絕對路徑不包含符號鏈接。
-X, --exclude-pattern=pattern 排除某規則下的路徑。
crontab定時
cron工具是一個以系統服務的形式存在。通過/etc/rc.d/init.d 或者 /etc/init.d目錄下的啟動腳本crond來啟動。 也可能直接通過 service crond start 命令來啟動。
cron不停地檢查所有配置的任務在當前是否應該運行,任務運行的最小時間間隔是1分鍾,也就是說任務最頻繁只能每分鍾運行一次。
可用crontab -e命令來編輯,編輯的是/var/spool/cron下對應用戶的cron文件,也可以直接修改/etc/crontab文件。具體格式如下:
-
Minute Hour Day Month Week command
-
分鍾 小時 天 月 星期 命令
-
0-59 0-23 1-31 1-12 0-6 command
/var/log/cron 是crontab的日志
具體的配置參考如下的目錄中的內容
/etc/cron.hourly
/etc/cron.daily
tmpfiles服務
系統使用systemd管理易變與臨時文件,與之相關的系統服務有3個:
systemd-tmpfiles-setup.service :Create Volatile Files and Directories
systemd-tmpfiles-setup-dev.service:Create static device nodes in /dev
systemd-tmpfiles-clean.service :Cleanup of Temporary Directories
相關的配置文件也有3個地方:
/etc/tmpfiles.d/*.conf
/run/tmpfiles.d/*.conf
/usr/lib/tmpfiles.d/*.conf
/tmp目錄的清理規則主要取決於/usr/lib/tmpfiles.d/tmp.conf文件的設定
對於不同目錄下的同名配置文件, 僅以優先級最高的目錄中的那一個為准。 具體說來就是: /etc/
的優先級最高、 /run/
的優先級居中、 /usr/lib/
的優先級最低。 軟件包應該將自帶的配置文件安裝在 /usr/lib/
目錄中, 而 /etc/
目錄僅供系統管理員使用。 所有的配置文件,無論其位於哪個目錄中,都統一按照文件名的字典順序處理。 如果在多個配置文件中設置了同一個路徑(文件或目錄), 那么僅以文件名最靠前(字典順序)的那一個為准, 其他針對同一個路徑的配置項將會作為警告信息記錄到錯誤日志中。 如果有兩行互為前后綴, 那么始終是先處理前綴、再處理后綴。 所有帶有shell風格通配符的行, 都在所有不帶通配符的行之后處理。 如果有多個操作符應用於同一個文件(例如 ACL, xattr, 文件屬性調整), 那么將始終按固定的順序操作。 對於其他情況, 文件與目錄總是按照它們在配置文件中出現的順序處理。
如果系統管理員想要屏蔽 /usr/lib/
目錄中的某個配置文件, 那么最佳做法是在 /etc/
目錄中 創建一個指向 /dev/null
的同名符號鏈接, 即可徹底屏蔽 /usr/lib/
目錄中的同名文件。
配置文件格式
配置文件的格式是每行對應一個路徑,包含如下字段: 類型, 路徑, 權限, 屬主, 屬組, 壽命, 參數
#Type Path Mode UID GID Age Argument
d /run/user 0755 root root 10d -
L /tmp/foobar - - - - /dev/null
字段值可以用引號界定,並可以包含C風格的轉義字符。
類型(Type)
"類型"字段由一個單獨的、表示類型的字母與一個可選的感嘆號(!)組成。
可以識別的類型如下:
-
f
若指定的文件不存在,則創建它,否則什么也不做。 若設置了"參數"字段,則將其內容寫入指定的文件。 不追蹤軟連接。
-
F
若指定的文件不存在,則創建它,否則清空已有文件。 若設置了"參數"字段,則將其內容寫入指定的文件。不追蹤軟連接。
-
w
若指定的文件存在,則將"參數"字段的內容寫入該文件,否則什么也不做。 注意:不會在"參數"字段內容的末尾添加額外的換行符, 可以在"參數"字段中使用C語言風格的轉義字符。 可以在"路徑"字段中使用shell風格的通配符。 追蹤軟連接。
-
d
創建指定的目錄並賦於指定的UID/GID與權限。 如果指定的目錄已經存在,那么僅調整UID/GID與權限。 如果指定了"壽命"字段,那么該目錄中的內容將遵守基於時間的清理策略。
-
D
與
d
類似, 但是如果使用了--remove
選項,那么將會清空目錄中的所有內容。 -
e
與
d
類似,但是並不創建原本不存在的目錄。 可以在"路徑"字段中使用shell風格的通配符。 要想讓此類型有效,必須至少明確設置 權限, 屬主, 屬組, 壽命 字段之一。 如果"壽命"字段的值為 "0
" , 那么每次運行 systemd-tmpfiles --clean 命令都會無條件的清空該目錄。 這個特性經常與!
一起使用(參見后文的"例子"小節)。 -
v
如果指定的路徑不存在, 並且該路徑位於一個Btrfs子卷中, 那么按照指定的路徑創建子卷。 否則,創建一個普通的目錄(與
d
一樣)。 僅對Btrfs文件系統有意義。 此處創建的子卷不會被分配給任何 higher-level 配額組(quota group), 如果想要創建簡單的配額組層次關系, 那么應該使用下面的q
或Q
。 -
q
與
v
類似, 但會將所創建的新子卷分配給父子卷(父目錄) 所屬的 higher-level 配額組(quota group)。 這樣可以確保作用於父子卷(父目錄)的 higher-level 配額組 可以包含此處創建的新子卷(子目錄)。 僅對Btrfs文件系統有意義, 在非Btrfs文件系統上與d
等價。 如果指定的子卷(路徑)已經存在, 並且已經被分配給了一個或多個 higher-level 配額組,那么不修改任何現有的配額層次關系。 參見下面的Q
以及 btrfs-qgroup(8) 手冊,以了解更多關於btrfs的配額組(quota group)的概念。 -
Q
與
q
類似, 但並不直接復用父子卷(父目錄)的 higher-level 配額組(quota group), 而是首先找到父子卷(父目錄)的 最低級非葉子配額組(也就是倒數第二級配額組), 然后在此配額組與最末端的葉子配額組之間, 插入一個level值減一的"中間配額組", 並且與新建的子卷共享同一個ID。 如果父子卷(父目錄)不存在 higher-level 配額組, 那么插入一個level值為255且ID與新建子卷相同的"中間配額組", 並且這個新建的"中間配額組"將被指定為 父子卷(父目錄)的 higher-level 配額組(quota group), 同時,新建子卷的葉子配額組也會分配給它(中間配額組)。單就新建子卷自身而言,q
與Q
在實際效果上並無不同, 但是通過插入一個新的 higher-level 配額組,Q
可以實現對該新建的子卷以及 未來創建在該子卷之下的下級子卷進行統一的配額限制。 這樣,在通過q
與Q
創建子卷的同時,也一起實現了一顆"配額子樹"。 每一個Q
創建的子卷都將擁有一個自己專屬的配額層次結構(配額子樹), 可用於容納將來創建的下級子卷。 每一個q
創建的子卷都沒有自己專屬的配額子樹, 其自身會被添加到直屬父子卷(父目錄)所屬的配額子樹中。Q
通常用於/home
或/var/lib/machines
這樣的目錄, 其特點是: 不但需要包含多個下級子卷, 而且需要將所有下級子卷視為一個整體進行配額限制。q
通常用於/var
或/var/tmp
這樣的目錄, 其特點是: 要么不需要包含下級子卷, 要么不需要將所有下級子卷視為一個整體進行配額限制。 與q
一樣,Q
也不會改變任何已經存在的配額層次關系,也就是說, 如果指定的子卷(路徑)已經存在,並且已經被分配給了一個或多個 higher-level 配額組, 那么不修改任何現有的配額層次關系。 -
p
,p+
若指定的管道(FIFO)不存在,則創建它,否則什么也不做。 后綴
+
表示:若指定的路徑已存在一個非管道文件, 則先刪除此文件再創建指定的管道文件。 -
L
,L+
若指定的軟連接不存在,則創建它,否則什么也不做。 后綴
+
表示: 若指定的路徑已存在一個非軟連接文件或目錄, 則先刪除此文件或目錄再創建指定的軟連接。 若"參數"字段為空, 那么將創建一個指向/usr/share/factory/
目錄中同名文件的軟連接。 注意,軟連接的UID/GID與權限將被忽略。 -
c
,c+
若指定的字符設備不存在,則創建它,否則什么也不做。 后綴
+
表示: 若指定的路徑已存在一個非字符設備的文件, 則先刪除此文件再創建指定的字符設備。 因為udev並不管理運行時創建的靜態設備節點, 所以建議在末尾加上"!",以確保僅在系統啟動期間才創建此靜態設備節點。 -
b
,b+
若指定的塊設備不存在,則創建它,否則什么也不做。 后綴
+
表示: 若指定的路徑已存在一個非塊設備的文件, 則先刪除此文件再創建指定的塊設備。 因為udev並不管理在運行時創建的靜態設備節點, 所以建議在末尾加上"!",以確保僅在系統啟動期間才創建此靜態設備節點。 -
C
若指定的文件或目錄不存在, 則遞歸的從"參數"字段所指定的文件或目錄復制, 否則什么也不做。 若"參數"字段為空, 那么將從
/usr/share/factory/
目錄中 遞歸的復制同名文件或目錄。 不追蹤軟連接。 -
x
在根據"壽命"字段清理過期文件時, 忽略指定的路徑及該路徑下的所有內容。 可以在"路徑"字段中使用shell風格的通配符。 注意,這個保護措施對
r
與R
無效。 -
X
在根據"壽命"字段清理過期文件時, 僅忽略指定的路徑自身而不包括該路徑下的其他內容。 可以在"路徑"字段中使用shell風格的通配符。 注意,這個保護措施對
r
與R
無效。 -
r
若指定的文件或目錄存在,則刪除它。 不可用於非空目錄。 可以在"路徑"字段中使用shell風格的通配符。 不追蹤軟連接。
-
R
若指定的文件或目錄存在,則遞歸的刪除它。 可用於非空目錄。可以在"路徑"字段中使用shell風格的通配符。 不追蹤軟連接。
-
z
若指定的文件或目錄存在, 則僅設置其自身的訪問權限、屬主、屬組、重置SELinux安全上下文。 可以在"路徑"字段中使用shell風格的通配符。 不追蹤軟連接。
-
Z
若指定的文件或目錄存在, 則遞歸的設置其訪問權限、屬主、屬組、重置SELinux安全上下文。 可以在"路徑"字段中使用shell風格的通配符。 不追蹤軟連接。
-
t
若指定的文件或目錄存在, 則僅設置其自身的SMACK標簽。 可以在"路徑"字段中使用shell風格的通配符。 不追蹤軟連接。
-
T
若指定的文件或目錄存在, 則遞歸的設置其SMACK標簽。 可以在"路徑"字段中使用shell風格的通配符。 不追蹤軟連接。
-
h
若指定的文件或目錄存在,則僅調整其自身的屬性。 可以在"路徑"字段中使用shell風格的通配符。"參數"字段的格式是
[+-=][aAcCdDeijsStTu]
, 具體解釋如下:+
前綴表示添加屬性(這是默認值);-
前綴表示去除屬性;=
前綴表示設置屬性(但對 "aAcCdDeijsStTu
" 范圍之外的其他屬性沒有影響); 而后綴字母 "aAcCdDeijsStTu
" 則用於表示各種屬性, 其含義與 chattr(1) 手冊里的解釋一致。注意,將"參數"字段設為一個單獨的=
(無后繼字母) 表示重置所有 "aAcCdDeijsStTu
" 代表的屬性。 不追蹤軟連接。 -
H
若指定的文件或目錄存在,則遞歸的調整其屬性。 可以在"路徑"字段中使用shell風格的通配符。 不追蹤軟連接。"參數"字段的語法與
h
完全相同。 -
a
,a+
若指定的文件或目錄存在, 則僅設置其自身的訪問控制列表(POSIX ACL)。 可以在"路徑"字段中使用shell風格的通配符。 后綴
+
表示將指定的項添加到已有的訪問控制列表中。 除非基本權限已經存在或被明確指定, 否則 systemd-tmpfiles 將會自動根據"權限","屬主","屬組"字段添加所需的基本權限。 如果沒有明確指定訪問控制列表或者訪問控制列表已經存在, 那么將會疊加上掩碼。 不追蹤軟連接。 -
A
,A+
若指定的文件或目錄存在,則遞歸的設置訪問控制列表(POSIX ACL)。 其他與
a
/a+
完全相同。 不追蹤軟連接。
使用了感嘆號(!)標記的行,僅可用於系統啟動過程中, 禁止用於運行中的系統(會破壞系統的正常運行)。 未使用感嘆號(!)標記的行, 可以在任意時間安全的執行(例如升級軟件包的時候)。 systemd-tmpfiles 僅在明確使用了 --boot
選項的時候才會執行使用了感嘆號(!)標記的行。
例如:
# 確保默認創建此目錄
d /tmp/.X11-unix 1777 root root 10d
# 僅在系統啟動時清理X11的鎖文件(但在運行時禁止刪除這些文件)
r! /tmp/.X[0-9]*-lock
本例中的第二行僅在明確使用了 --boot
選項的時候才會執行, 因為它會破壞正在運行中的系統。 但是第一行則無此限制,可以在任何時候執行都不會對系統造成損害。
路徑(Path)
"路徑"字段是指文件系統路徑, 並且支持幾個簡單的替換標記:
表 1. 可用於替換的標記
標記
含義
解釋
"%m
"
Machine ID
系統的"Machine ID"字符串。參見 machine-id(5) 手冊。
"%b
"
Boot ID
系統的"Boot ID"字符串。參見 random(4) 手冊。
"%H
"
Host name
系統的主機名(hostname)
"%v
"
Kernel release
內核版本(uname -r 的輸出)
"%%
"
Escaped %
百分號自身(%)。使用"%%"表示一個真正的"%"字符。
權限(Mode)
"權限"字段表示設置文件或目錄的權限, 如果省略或設為 "-
" 則表示使用默認權限, 也就是:對於目錄使用"0755"、對於文件使用"0644", 但對於 z
, Z
表示不修改現有的權限。 此字段對於 x
, r
, R
, L
, t
, a
沒有意義。
可選前綴 "~
" 的含義是掩碼, 也就是將此字段當作權限掩碼來使用。 換句話說,就是將此字段設置的值與現有的權限做"位與"運算。 舉例來說,假設原有文件的權限是"0765",此字段的值是"~1550", 那么文件的最終權限將是"0540"。 如果省略了 sticky/SUID/SGID 位, 那么對於文件來說相當於全部清除, 而對於目錄來說則相當於保持不變。 例如"~550",對於文件來說相當於"~0550", 而對於目錄來說則相當於"~7550"。 此特性在實踐中僅對 Z
有實際價值。
屬主,屬組(UID,GID)
"屬主"與"屬組"字段分別表示文件或目錄的所屬用戶與所屬用戶組。 可以設為數字形式的UID/GIU值,也可以設為字符串形式的用戶名稱/組名稱。 如果省略或者設為 "-
" 則表示使用默認值"0"(root)。 但對於 z
與 Z
來說,省略或者設為 "-
" 則表示不修改現有的"屬主"與"屬組"。 此字段對於 x
, r
, R
, L
, t
, a
沒有意義。
壽命(Age)
"壽命"字段用於判定在清理過期文件或子目錄時應該刪除哪些, 也就是決定了文件或子目錄的"壽命"。 如果文件或子目錄的最后改動時間(ctime) 與當前系統時間之差已經大於"壽命"字段的值, 那么這些文件或子目錄將被刪除。 此字段的值是一個時間長度, 可以使用下面的時間單位后綴: us
(微秒), ms
(毫秒), s
(秒), m
(分), h
(時), d
(天), w
(周)。
可以同時使用多個時間單位, 例如"5m10s"表示5分10秒(也就是310秒)。 如果省略了時間單位,那么表示使用默認單位"秒"。
如果將此字段設為數字"0", 那么表示在每次清理時都無條件的刪除所有文件或子目錄。
此字段僅對 d
, D
, e
, v
, q
, Q
, C
, x
, X
有意義。如果省略此字段或將其設為 "-
" ,那么表示不進行任何清理。
如果此字段的值以 "~
" 開頭, 那么表示在每次清理時都無條件的保留指定目錄直屬的文件與子目錄, 也就是僅清理直屬子目錄下的內容。
參數(Argument)
"參數"字段對不同的"類型"有不同的作用: 對於 L
來說,用於指定軟連接的目標路徑。 對於 c
, b
來說, 用於以"主設備號:次設備號"的格式設定設備節點的主/次設備號(十進制整數), 例如 "1:3
" 。 對於 f
, F
, w
來說, 用於設置一個寫入文件的短字符串(實際寫入時會在末尾附加一個換行符)。 對於 C
來說,用於指定源文件或者源目錄。 對於 t
, T
來說, 用於指定將要設置的擴展屬性。 對於 a
, A
來說,用於指定將要設置的ACL屬性。 對於 h
, H
來說,用於指定將要設置的文件屬性。 對於其他類型無意義,將被忽略。
例子
例 1. 按照指定的UID/GID與權限創建目錄
screen(1) 需要在系統啟動時按照指定的屬主/屬組/權限創建兩個目錄
# /usr/lib/tmpfiles.d/screen.conf
d /run/screens 1777 root screen 10d
d /run/uscreens 0755 root screen 10d12h
/run/screens
中超過10天的內容將被清理。 /run/uscreens
中超過10.5天的內容將被清理。
例 2. 創建一個帶有 SMACK 屬性的目錄
D /run/cups - - - -
t /run/cups - - - - security.SMACK64=printing user.attr-with-spaces="foo bar"
該目錄的屬主將是"root"並且會被賦予默認權限。 目錄中的內容將不會被定期清理,但可使用 systemd-tmpfiles --remove 命令清除。
例 3. 創建一個不會被定期清理的目錄
abrt(1) 需要在系統啟動時按照指定的屬主/屬組/權限創建一個目錄, 並且禁止清理 /var/tmp
目錄
# /usr/lib/tmpfiles.d/tmp.conf
d /var/tmp 1777 root root 30d
# /usr/lib/tmpfiles.d/abrt.conf
d /var/tmp/abrt 0755 abrt abrt -
例 4. 啟用系統啟動過程中的清理,以及基於時間的清理
# /usr/lib/tmpfiles.d/dnf.conf
r! /var/cache/dnf/*/*/download_lock.pid
r! /var/cache/dnf/*/*/metadata_lock.pid
r! /var/lib/dnf/rpmdb_lock.pid
e /var/cache/dnf/ - - - 30d
系統啟動過程中將會清理 lock 文件。 /var/cache/dnf/
目錄中閑置超過30天的內容將會被刪除。
例 5. 在啟動時清空緩存目錄
# /usr/lib/tmpfiles.d/krb5rcache.conf
e! /var/cache/krb5rcache - - - 0
在啟動時清空 /var/cache/krb5rcache/
下的所有內容。即使此目錄不存在也不會創建它。