Linux系統查看當前主機CPU、內存、機器型號及主板信息:
查看CPU信息(型號)
# cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c
查看內存信息
# cat /proc/meminfo
查看主板型號:
# dmidecode |grep -A16 "System Information$"
查看機器型號
# dmidecode | grep "Product Name"
查看當前操作系統內核信息
# uname -a
查看當前操作系統發行版信息
# cat /etc/issue | grep Linux
所有日期、時間的api都在datetime模塊內。
1. datetime => string
now = datetime.datetime.now() now.strftime('%Y-%m-%d %H:%M:%S') #輸出2012-03-05 16:26:23.870105
strftime是datetime類的實例方法。
2. string => datetime
t_str = '2012-03-05 16:26:23' d = datetime.datetime.strptime(t_str, '%Y-%m-%d %H:%M:%S')
strptime是datetime類的靜態方法。
在datetime模塊中有timedelta類,這個類的對象用于表示一個時間間隔,比如兩個日期或者時間的差別。
構造方法:
datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)
所有的參數都有默認值0,這些參數可以是int或float,正的或負的。
可以通過timedelta.days、tiemdelta.seconds等獲取相應的時間值。
timedelta類的實例,支持加、減、乘、除等操作,所得的結果也是timedelta類的實例。比如:
year = timedelta(days=365) ten_years = year *10 nine_years = ten_years - year
同時,date、time和datetime類也支持與timedelta的加、減運算。
datetime1 = datetime2 +/- timedelta
timedelta = datetime1 - datetime2
這樣,可以很方便的實現一些功能。
1. 兩個日期相差多少天。
d1 = datetime.datetime.strptime('2012-03-05 17:41:20', '%Y-%m-%d %H:%M:%S') d2 = datetime.datetime.strptime('2012-03-02 17:41:20', '%Y-%m-%d %H:%M:%S') delta = d1 - d2 print delta.days
輸出:3
2. 今天的n天后的日期。
now = datetime.datetime.now() delta = datetime.timedelta(days=3) n_days = now + delta print n_days.strftime('%Y-%m-%d %H:%M:%S')
輸出:2012-03-08 17:44:50
#coding=utf-8 import datetime now=datetime.datetime.now() print now #將日期轉化為字符串 datetime => string print now.strftime('%Y-%m-%d %H:%M:%S') t_str = '2012-03-05 16:26:23' #將字符串轉換為日期 string => datetime d=datetime.datetime.strptime(t_str,'%Y-%m-%d %H:%M:%S') print d #在datetime模塊中有timedelta類,這個類的對象用于表示一個時間間隔,比如兩個日#期或者時間的差別。 #計算兩個日期的間隔 d1 = datetime.datetime.strptime('2012-03-05 17:41:20', '%Y-%m-%d %H:%M:%S') d2 = datetime.datetime.strptime('2012-03-02 17:41:20', '%Y-%m-%d %H:%M:%S') delta = d1 - d2 print delta.days print delta #今天的n天后的日期。 now=datetime.datetime.now() delta=datetime.timedelta(days=3) n_days=now+delta print n_days.strftime('%Y-%m-%d %H:%M:%S')
Shell中并沒有真正意義的多線程,要實現多線程可以啟動多個后端進程,最大程度利用cpu性能。
直接看代碼示例吧。
(1) 順序執行的代碼
輸出:
(2) 并行代碼
使用'&'+wait 實現“多進程”實現
1 #!/bin/bash 2 date 3 for i in `seq 1 5` 4 do 5 { 6 echo "sleep 5" 7 sleep 5 8 } & 9 done 10 wait ##等待所有子后臺進程結束 11 date
輸出:
(3) 對于大量處理任務如何實現啟動后臺進程的數量可控?
簡單的方法可以使用2層for/while循環實現,每次wait內層循環的多個后臺程序執行完成。
但是這種方式的問題是,如果內層循環有“慢節點”可能導致整個任務的執行執行時間長。
更高級的實現可以看(4)
(4) 使用命名管道(fifo)實現每次啟動后臺進程數量可控。
1 #!/bin/bash 2 3 function my_cmd(){ 4 t=$RANDOM 5 t=$[t%15] 6 sleep $t 7 echo "sleep $t s" 8 } 9 10 tmp_fifofile="/tmp/$$.fifo" 11 mkfifo $tmp_fifofile # 新建一個fifo類型的文件 12 exec 6<>$tmp_fifofile # 將fd6指向fifo類型 13 rm $tmp_fifofile #刪也可以 14 15 thread_num=5 # 最大可同時執行線程數量 16 job_num=100 # 任務總數 17 18 #根據線程總數量設置令牌個數 19 for ((i=0;i<${thread_num};i++));do 20 echo 21 done >&6 22 23 for ((i=0;i<${job_num};i++));do # 任務數量 24 # 一個read -u6命令執行一次,就從fd6中減去一個回車符,然后向下執行, 25 # fd6中沒有回車符的時候,就停在這了,從而實現了線程數量控制 26 read -u6 27 28 #可以把具體的需要執行的命令封裝成一個函數 29 { 30 my_cmd 31 } & 32 33 echo >&6 # 當進程結束以后,再向fd6中加上一個回車符,即補上了read -u6減去的那個 34 done 35 36 wait 37 exec 6>&- # 關閉fd6 38 echo "over"
參考:http://lawrence-zxc.github.io/2012/06/16/shell-thread/
之前在論壇看到一個關于HDFS權限的問題,當時無法回答該問題。無法回答并不意味著對HDFS權限一無所知,而是不能準確完整的闡述HDFS權限,因此決定系統地學習HDFS文件權限。HDFS的文件和目錄權限模型共享了POSIX(Portable Operating System Interface,可移植操作系統接口)模型的很多部分,比如每個文件和目錄與一個擁有者和組相關聯,文件或者目錄對于擁有者、組內的其它用戶和組外的其它用戶有不同的權限等。與POSIX模型不同的是,HDFS中的文件沒有可執行文件的概念,因而也沒有setuid和setgid,雖然目錄依然保留著可執行目錄的概念(x),但對于目錄也沒有setuid和setgid。粘貼位(sticky bit)可以用在目錄上,用于阻止除超級用戶,目錄或文件的擁有者外的任何刪除或移動目錄中的文件,文件上的粘貼位不起作用。
當創建文件或目錄時,擁有者為運行客戶端進程的用戶,組為父目錄所屬的組。每個訪問HDFS的客戶端進程有一個由用戶姓名和組列表兩部分組的成標識,無論何時HDFS必須對由客戶端進程訪問的文件或目錄進行權限檢查,規則如下:
如果權限檢查失敗,則客戶端操作失敗。
從hadoop-0.22開始,hadoop支持兩種不同的操作模式以確定用戶,分別為simple和kerberos具體使用哪個方式由參數hadoop.security.authentication設置,該參數位于core-site.xml文件中,默認值為simple。在simple模式下,客戶端進程的身份由主機的操作系統確定,比如在類Unix系統中,用戶名為命令whoami的輸出。在kerberos模式下,客戶端進程的身份由Kerberos憑證確定,比如在一個Kerberized環境中,用戶可能使用kinit工具得到了一個Kerberos ticket-granting-ticket(TGT)且使用klist確定當前的principal。當映射一個Kerberosprincipal到HDFS的用戶名時,除了最主要的部分外其余部分都被丟棄,比如一個principal為todd/foobar@CORP.COMPANY.COM,將映射為HDFS上的todd。無論哪種操作模式,對于HDFS來說用戶標識機制都是外部的,HDFS本身沒有創建用戶標,建立組或者處理用戶憑證的規定。
上面討論了確定用戶的兩種模式,即simple和kerberos,下面學習如何確定用戶組。用戶組是通過由參數hadoop.security.group.mapping設置的組映射服務確定的,默認實現是org.apache.hadoop.security.JniBasedUnixGroupsMappingWithFallback,該實現首先確定Java本地接口(JNI)是否可用,如果JNI可用,該實現將使用hadoop中的API為用戶解析用戶組列表。如果JNI不可用,那么使用ShellBasedUnixGroupsMapping,該實現將使用Linux/Unix中的bash –cgroups命令為用戶解析用戶組列表。其它實現還有LdapGroupsMapping,通過直接連接LDAP服務器來解析用戶組列表。對HDFS來說,用戶到組的映射是在NameNode上執行的,因而NameNode的主機系統配置決定了用戶的組映射。HDFS將文件或目錄的用戶和組存儲為字符串,并且不像Linux/Unix那樣可以將用戶和組轉換為數字。
每個針對文件或者目錄的操作都將全路徑名稱傳遞到NameNode,然后對該路徑的每次操作都將應用權限檢查??蛻舳穗[含地關聯用戶身份到NameNode的連接,減少改變現存客戶端API的需要。總是存在這么一種情景,當在一個文件上的操作成功后,當重復該操作時可能失敗,因為該文件或者路徑中的某些目錄已經不再存在。例如,當客戶端第一次開始讀取一個文件時,它向NameNode發出的第一個請求來發現該文件第一個塊的位置,第二個尋找其他塊的請求可能失敗。另一方面,對于已經知道文件塊的客戶端來說,刪除文件不會取消訪問。通過添加權限,客戶端對文件的訪問在請求之間可能撤回,對于已經知道文件塊的客戶端來說,改變權限不會取消客戶端的訪問。
HDFS中超級用戶與通常熟悉的Linux或Unix中的root用戶不同,HDFS的超級用戶是與NameNode進程有相同標示的用戶,更簡單易懂些,啟動NameNode的用戶就為超級用戶。對于誰是超級用戶沒有固定的定義,當NameNode啟動后,該進程的標示決定了誰是超級用戶。HDFS的超級用戶不必是NameNode主機的超級用戶,也需用所有的集群使用相同的超級用戶,出于實驗目的在個人工作站上運行HDFS的人自然而然的稱為超級用戶而不需要任何配置。另外參數dfs.permissions.superusergroup設置了超級用戶,該組中的所有用戶也為超級用戶。超級用戶在HDFS中可以執行任何操作而針對超級用戶的權限檢查永遠不會失敗。
HDFS也提供了對POSIX ACL(訪問控制列表)支持來為特定的用戶或者用戶組提供更加細粒度的文件權限。ACL是不同于用戶和組的自然組織層次的有用的權限控制方式,ACL可以為特定的用戶和組設置不同的權限,而不僅僅是文件的擁有者和文件所屬的組。默認情況下,HDFS禁用ACL,因此NameNode禁止ACL的創建,為了啟用ACL,需要在hdfs-site.xml中將參數dfs.namenode.acls.enabled設置為true。
訪問控制列表由一組ACL項組成,每個ACL項命名了特定的用戶或組,并為其授予或拒絕讀,寫和執行的權限,例如:
user::rw- user:bruce:rwx #effective:r-- group::r-x #effective:r-- group:sales:rwx #effective:r-- mask::r-- other::r--
每個ACL項由類型,可選的名稱和權限字符串組成,它們之間使用冒號(:)。在上面的例子中文件的擁有者具有讀寫權限,文件所屬的組具有讀和執行的權限,其他用戶具有讀權限,這些設置與將文件設置為654等價(6表示擁有者的讀寫權限,5表示組的讀和執行權限,4表示其他用戶的讀權限)。除此之外,還有兩個擴展的ACL項,分別為用戶bruce和組sales,并都授予了讀寫和執行的權限。mask項是一個特殊的項,用于過濾授予所有命名用戶,命名組及未命名組的權限,即過濾除文件擁有者和其他用戶(other)之外的任何ACL項。在該例子中,mask值有讀權限,則bruce用戶、sales組和文件所屬的組只具有讀權限。每個ACL必須有mask項,如果用戶在設置ACL時沒有使用mask項,一個mask項被自動加入到ACL中,該mask項是通過計算所有被mask過濾項的權限與(&運算)得出的。對擁有ACL的文件執行chmod實際改變的是mask項的權限,因為mask項扮演的是過濾器的角色,這將有效地約束所有擴展項的權限,而不是僅改變組的權限而可能漏掉其它擴展項的權限。
訪問控制列表和默認訪問控制列表存在著不同,前者定義了在執行權限檢查實施的規則,后者定義了新文件或者子目錄創建時自動接收的ACL項,例如:
user::rwx group::r-x other::r-x default:user::rwx default:user:bruce:rwx #effective:r-x default:group::r-x default:group:sales:rwx #effective:r-x default:mask::r-x default:other::r-x
只有目錄可能擁有默認訪問控制列表,當創建新文件或者子目錄時,自動拷貝父輩的默認訪問控制列表到自己的訪問控制列表中,新的子目錄也拷貝父輩默認的訪問控制列表到自己的默認訪問控制列表中。這樣,當創建子目錄時默認ACL將沿著文件系統樹被任意深層次地拷貝。在新的子ACL中,準確的權限由模式參數過濾。默認的umask為022,通常新目錄權限為755,新文件權限為644。模式參數為未命名用戶(文件的擁有者),mask及其他用戶過濾拷貝的權限值。在上面的例子中,創建權限為755的子目錄時,模式對最終結果沒有影響,但是如果創建權限為644的文件時,模式過濾器導致新文件的ACL中文件擁有者的權限為讀寫,mask的權限為讀以及其他用戶權限為讀。mask的權限意味著用戶bruce和組sales只有讀權限??截怉CL發生在文件或子目錄的創建時,后面如果修改父輩的默認ACL將不再影響已存在子類的ACL。
默認ACL必須包含所有最小要求的ACL項,包括文件擁有者項,文件所屬的組項和其它用戶項。如果用戶沒有在默認ACL中配置上述三項中的任何一個,那么該項將通過從訪問ACL拷貝對應的權限來自動插入,或者如果沒有訪問ACL則自動插入權限位。默認ACL也必須擁有mask,如果mask沒有被指定,通過計算所有被mask過濾項的權限與(&運算)自動插入mask。當一個文件擁有ACL時,權限檢查的算法變為:
最佳實踐時基于傳統的權限位設置大部分權限要求,然后定義少量帶有特殊規則的ACL增加權限位。相比較只是用權限位的文件,使用ACL的文件會在NameNode中產生額外的內存消耗。
上面學習了HDFS中的文件權限和訪問控制列表,最后學習一下如何針對權限和ACL進行配置,下表列出了其中的重要參數:
參數名 | 位置 | 用途 |
dfs.permissions.enabled | hdfs-site.xml | 默認值為true,即啟用權限檢查。如果為 false,則禁用權限檢查。 |
hadoop.http.staticuser.user | core-site.xml | 默認值為dr.who,查看web UI的用戶 |
dfs.permissions.superusergroup | hdfs-site.xml | 超級用戶的組名稱,默認為supergroup |
<fs.permissions.umask-mode | core-site.xml | 創建文件和目錄時使用的umask,默認值為八進制022,每位數字對應了擁有者,組和其他用戶。該值既可以使用八進制數字,如022,也可以使用符號,如u=rwx,g=r-x,o=r-x(對應022) |
dfs.cluster.administrators | hdfs-site.xml | 被指定為ACL的集群管理員 |
dfs.namenode.acls.enabled | hdfs-site.xml | 默認值為false,禁用ACL,設置為true則啟用ACL。當ACL被禁用時,NameNode拒絕設置或者獲取ACL的請求 |