數(shù)據(jù)庫(kù)鏈接 常見(jiàn)的問(wèn)題:
1. 數(shù)據(jù)庫(kù)意外重啟后,原先的數(shù)據(jù)庫(kù)連接池能自動(dòng)廢棄老的無(wú)用的鏈接,建立新的數(shù)據(jù)庫(kù)鏈接
2. 網(wǎng)絡(luò)異常中斷后,原先的建立的tcp鏈接,應(yīng)該能進(jìn)行自動(dòng)切換。比如網(wǎng)站演習(xí)中的交換機(jī)重啟會(huì)導(dǎo)致網(wǎng)絡(luò)瞬斷
3. 分布式數(shù)據(jù)庫(kù)中間件,比如cobar會(huì)定時(shí)的將空閑鏈接異常關(guān)閉,客戶(hù)端會(huì)出現(xiàn)半開(kāi)的空閑鏈接。
大致思考解決思路:
1. sql心跳檢查(主動(dòng)式)
2. 拿鏈接嘗試一下,發(fā)現(xiàn)處理失敗丟棄鏈接,探雷的請(qǐng)求會(huì)失敗幾個(gè) (犧牲小我,完成大我的精神)
3. 設(shè)置合理的空閑鏈接的超時(shí)時(shí)間,避免半開(kāi)鏈接(懶模式,解決半開(kāi)鏈接)
下面我們來(lái)看看,在dbcp中是如何實(shí)現(xiàn)。
sql心跳檢查
sql validate配置
<property name="testWhileIdle"><value>true</value></property>
<property name="testOnBorrow"><value>false</value></property>
<property name="testOnReturn"><value>false</value></property>
<property name="validationQuery"><value>select sysdate from dual</value></property>
<property name="validationQueryTimeout"><value>1</value></property>
<property name="timeBetweenEvictionRunsMillis"><value>30000</value></property>
<property name="numTestsPerEvictionRun"><value>16</value></property>
參數(shù)說(shuō)明
dbcp是采用了commons-pool做為其連接池管理,testOnBorrow,testOnReturn, testWhileIdle是pool是提供的幾種校驗(yàn)機(jī)制,通過(guò)外部鉤子的方式回調(diào)dbcp的相關(guān)數(shù)據(jù)庫(kù)鏈接(validationQuery)校驗(yàn), dbcp相關(guān)外部鉤子類(lèi):PoolableConnectionFactory,繼承于common-pool PoolableObjectFactory , dbcp通過(guò)GenericObjectPool這一入口,進(jìn)行連接池的borrow,return處理。
具體參數(shù)描述:
1. testOnBorrow : 顧明思義,就是在進(jìn)行borrowObject進(jìn)行處理時(shí),對(duì)拿到的connection進(jìn)行validateObject校驗(yàn)
2. testOnReturn : 顧明思義,就是在進(jìn)行returnObject對(duì)返回的connection進(jìn)行validateObject校驗(yàn),個(gè)人覺(jué)得對(duì)數(shù)據(jù)庫(kù)連接池的管理意義不大
3. testWhileIdle : 關(guān)注的重點(diǎn),GenericObjectPool中針對(duì)pool管理,起了一個(gè)異步Evict的TimerTask定時(shí)線程進(jìn)行控制(可通過(guò)設(shè)置參數(shù) timeBetweenEvictionRunsMillis>0),定時(shí)對(duì)線程池中的鏈接進(jìn)行validateObject校驗(yàn),對(duì)無(wú)效的鏈接進(jìn)行關(guān)閉后,會(huì)調(diào)用ensureMinIdle,適當(dāng)建立鏈接保證最小的minIdle連接數(shù)。
4. timeBetweenEvictionRunsMillis,設(shè)置的Evict線程的時(shí)間,單位ms,大于0才會(huì)開(kāi)啟evict檢查線程
5. validateQuery, 代表檢查的sql
6. validateQueryTimeout, 代表在執(zhí)行檢查時(shí),通過(guò)statement設(shè)置,statement.setQueryTimeout(validationQueryTimeout)
7. numTestsPerEvictionRun,代表每次檢查鏈接的數(shù)量,建議設(shè)置和maxActive一樣大,這樣每次可以有效檢查所有的鏈接.
Sql心跳檢查幾點(diǎn)思考:
1.性能問(wèn)題。
目前網(wǎng)站的應(yīng)用大部分的瓶頸還是在I/O這一塊,大部分的I/O還是在數(shù)據(jù)庫(kù)的這一層面上,每一個(gè)請(qǐng)求可能會(huì)調(diào)用10來(lái)次SQL查詢(xún),如果不走事務(wù),一個(gè)請(qǐng)求會(huì)重復(fù)獲取鏈接,如果每次獲取鏈接,比如在testOnBorrow都進(jìn)行validateObject,性能開(kāi)銷(xiāo)不是很能接受,可以假定一次SQL操作消毫0.5~1ms(一般走了網(wǎng)絡(luò)請(qǐng)求基本就這數(shù))
2.成本和收益
網(wǎng)站異常數(shù)據(jù)庫(kù)重啟,網(wǎng)絡(luò)異常斷開(kāi)的頻率是非常低的,一般也就在數(shù)據(jù)庫(kù)升級(jí),演習(xí)維護(hù)時(shí)才會(huì)進(jìn)行,而且一般也是選在晚上,訪問(wèn)量相對(duì)比較低的請(qǐng)求,而且一般會(huì)有人員值班關(guān)注,所以異步的validateObject是可以接受,但一個(gè)前提需要確保能保證在一個(gè)合理的時(shí)間段內(nèi),數(shù)據(jù)庫(kù)能完成自動(dòng)重聯(lián)。
請(qǐng)求探雷
相關(guān)配置
dbcp自身默認(rèn)支持,不需要配置
原理描述
common-pools通過(guò)borrowObject , returnObject完成連接的獲取和釋放,正常的情況是一次請(qǐng)求中borrow和return是一對(duì)的,有借就有還。
但在準(zhǔn)備returnObject時(shí),dbcp會(huì)做一件事,就是看看這個(gè)object是否已經(jīng)是壞了的,如果壞了就直接丟了,就直接給丟棄了。
代碼層面:
1. 在dbcp中PoolingDataSource(實(shí)現(xiàn)DataSource接口)調(diào)用 PoolableConnection(dbcp connnection相關(guān)的pool delegate操作)進(jìn)行相應(yīng)關(guān)閉時(shí),會(huì)檢查_conn.isClosed(),針對(duì)DataSource如果isClosed返回為 true的則不調(diào)用returnObject,直接丟棄了鏈接。
2. _conn.isClosed()是否保險(xiǎn),從jdk的api描述中: A connection is closed if the method close has been called on it or if certain fatal errors have occurred. 里面提供兩種情況,一種就是被調(diào)用了closed方法,另一種就是出現(xiàn)一些異常,說(shuō)的比較含糊。
空閑鏈接檢查
相關(guān)配置
<property name="minEvictableIdleTimeMillis"><value>18000000</value></property>
<property name="removeAbandoned"><value>true</value></property>
<property name="removeAbandonedTimeout"><value>180</value></property>
參數(shù)說(shuō)明
1.minEvictableIdleTimeMillis dbcp默認(rèn)是30分,需要開(kāi)啟異步線程Evict,否則不生效。原理很簡(jiǎn)單,就是通過(guò)一個(gè)異步線程,每次檢查connnection上一次使用的時(shí)間戳,看看是否已經(jīng)超過(guò)這個(gè)timeout時(shí)間設(shè)置。
2. removeAbandoned , removeAbandonedTimeout,主要是用于在出現(xiàn)鏈接緊張時(shí)候,會(huì)掃描一些鏈接未超過(guò)removeAbandonedTimeout時(shí)間還未被釋放,會(huì)主動(dòng)的關(guān)閉該鏈接。
適用情況
1. 我們使用的cobar后端會(huì)有定時(shí)關(guān)閉空閑鏈接的操作,默認(rèn)的空閑鏈接timeout時(shí)間為1小時(shí),和其他oracle , mysql各不相同,所以設(shè)置好這個(gè)空閑鏈接的timeout時(shí)間還是挺重要.
2. 一般會(huì)是幾種情況出現(xiàn)需要removeAbandoned:
* 代碼未在finally釋放connection , 不過(guò)我們都用sqlmapClientTemplate,底層都有鏈接釋放的過(guò)程
* 遇到數(shù)據(jù)庫(kù)死鎖。以前遇到過(guò)后端存儲(chǔ)過(guò)程做了鎖表操作,導(dǎo)致前臺(tái)集群中連接池全都被block住,后續(xù)的業(yè)務(wù)處理因?yàn)槟貌坏芥溄铀卸继幚硎×恕?/span>
聊聊c3p0配置
還有我們配置的c3p0所謂的自動(dòng)重連的3個(gè)參數(shù),
<prop key="acquireRetryAttempts">30</prop>
<prop key="acquireRetryDelay">1000</prop>
<prop key="breakAfterAcquireFailure">false</prop>
個(gè)人覺(jué)得就是一個(gè)誤導(dǎo),這幾個(gè)配置只是在從連接池獲取鏈接時(shí),獲取失敗多嘗試幾次,因?yàn)槲覀儚膒ool從獲取鏈接最多只會(huì)等待固定timeout時(shí)間。
如果要達(dá)到自動(dòng)重連的效果,必須要c3p0支持請(qǐng)求探雷或者是sql心跳檢查功能,能自動(dòng)的剔除無(wú)效的鏈接?!?/span>
可見(jiàn)c3p0官方文檔描述:http://www.mchange.com/projects/c3p0/index.html#configuring_recovery
最后:
Dbcp將是我們以后數(shù)據(jù)庫(kù)驅(qū)動(dòng)選擇的趨勢(shì),最后我們?nèi)绾芜x擇如何自動(dòng)重連,這個(gè)也得根據(jù)我們的應(yīng)用場(chǎng)景而定。比如只讀的web系統(tǒng),后臺(tái)業(yè)務(wù)系統(tǒng),任務(wù)系統(tǒng)可能處理方式就不同。
只讀Web系統(tǒng):可采取請(qǐng)求探雷的策略,也就失敗連接池個(gè)數(shù)的請(qǐng)求,失敗了頁(yè)面刷新一次就好。
后臺(tái)業(yè)務(wù)系統(tǒng):一般業(yè)務(wù)都涉及數(shù)據(jù)庫(kù)的寫(xiě)操作,很多數(shù)據(jù)不可重入,一次處理失敗后就只能靠手工干預(yù)處理。這時(shí)候得考慮是否需要使用sql心跳檢查,比如testOnBorrow或者testWhileIdle.
1. 下載rsync (http://rsync.samba.org/)
安裝:
./configure
make
make install
2. 開(kāi)啟rsync服務(wù),修改/etc/xinetd.d/rsync
disable = no # replace <yes>
重啟xinetd 服務(wù)
service xinetd restart
3. 配置server端,/etc/rsyncd.conf
# touch rsyncd.conf
# vi rsyncd.conf
uid = ljh #表示以什么用戶(hù)運(yùn)行,注意必須確保該用戶(hù)有對(duì)模塊的讀寫(xiě)權(quán)限
gid = ljh
use chroot = false
max connectionts = 6
read only = no
pid file = /home/ljh/server/rsync/rsynnd.pid
lock file = /home/ljh/server/rsync/rsyncd.lock
log file = /home/ljh/server/rsync/rsyncd.log
[test]
comment = test
path = /home/ljh/server/rsync/data/test
ignore error
list = true
#auth users = ljh
#secrets file = /home/ljh/server/rsync/passwd/rsyncd.passwd













































4. 客戶(hù)端配置
訪問(wèn)remote rsync列表
rsync rsync://10.0.64.162/test
簡(jiǎn)單的執(zhí)行同步命令
sync -auv --delete --password-file=/home/admin2/soft/rsync/passwd/rsyncd.passwd ~/rysnc/* ljh@10.0.64.162::test
比較實(shí)際的例子:
echo "hello" > /tmp/password.txt ;chmod 600 /tmp/password.txt
cp /home/ewalletbops/fatrix/crm/* /home/ewalletbops/fatrix/putxml/search
rsync -azv /home/ewalletbops/bops-daemon/bin/adxml/search/ /home/ewalletbops/fatrix/putxml/search
rsync -auv --delete --password-file=/tmp/password.txt /home/ewalletbops/fatrix/putxml/search yangzhen@127.0.0.1::everest/adxml
rm /tmp/password.txt































































Tip1
1.在 JAVA_HOME/jre/lib/fonts/ 下建立個(gè)目錄 fallback
2.在 fallback 里弄個(gè)中文字體最簡(jiǎn)單ln一下就好了
比如:
ln -s /usr/share/fonts/truetype/arphic/uming.ttf $JAVA_HOME/jre/lib/fonts/fallback/
Tip2
問(wèn)題描述:Java 應(yīng)用程序的中文無(wú)法顯示,呈現(xiàn)方塊狀。
原因分析:Java 應(yīng)用程序無(wú)法找到可供顯示中文的字體。
解決方案:首先,確保系統(tǒng)里安裝了 JDK 1.5.0_06,如果安裝的是 JRE 1.5.0_06,那么卸掉 JRE,再安裝 JDK。然后下載 fireflysung 1.3.0, 解壓后將其中的 ttf 文件丟到系統(tǒng)字體目錄/usr/share/fonts,再用 fc-cache -f -v 跑一遍,讓系統(tǒng)知道這個(gè)字體。最后,就是轉(zhuǎn)到 JDK 安裝目錄的jre/lib/fonts 中,使用下面的命令來(lái)完成。
mkdir fallback cd fallback ln -s /usr/share/fonts/fireflysung.ttf mkfontdir mkfontscale
一、UNIX下關(guān)于文件權(quán)限的表示方法和解析
SUID 是 Set User ID, SGID 是 Set Group ID的意思。
UNIX下可以用ls -l 命令來(lái)看到文件的權(quán)限。用ls命令所得到的表示法的格式是類(lèi)似這樣的:-rwxr-xr-x 。下面解析一下格式所表示的意思。這種表示方法一共有十位:
9 8 7 6 5 4 3 2 1 0
- r w x r - x r - x
第9位表示文件類(lèi)型,可以為p、d、l、s、c、b和-:
p表示命名管道文件
d表示目錄文件
l表示符號(hào)連接文件
-表示普通文件
s表示socket文件
c表示字符設(shè)備文件
b表示塊設(shè)備文件
第8-6位、5-3位、2-0位分別表示文件所有者的權(quán)限,同組用戶(hù)的權(quán)限,其他用戶(hù)的權(quán)限,其形式為rwx:
r表示可讀,可以讀出文件的內(nèi)容
w表示可寫(xiě),可以修改文件的內(nèi)容
x表示可執(zhí)行,可運(yùn)行這個(gè)程序
沒(méi)有權(quán)限的位置用-表示
例子:
ls -l myfile顯示為:
rwxr-x-- 1 foo staff 7734 Apr 05 17:07 myfile
表示文件myfile是普通文件,文件的所有者是foo用戶(hù),而foo用戶(hù)屬于staff組,文件只有1個(gè)硬連接,長(zhǎng)度是7734個(gè)字節(jié),最后修改時(shí)間4月5日17:07。
所有者foo對(duì)文件有讀寫(xiě)執(zhí)行權(quán)限,staff組的成員對(duì)文件有讀和執(zhí)行權(quán)限,其他的用戶(hù)對(duì)這個(gè)文件沒(méi)有權(quán)限。
如果一個(gè)文件被設(shè)置了SUID或SGID位,會(huì)分別表現(xiàn)在所有者或同組用戶(hù)的權(quán)限的可執(zhí)行位上。例如:
1、-rwsr-xr-x 表示SUID和所有者權(quán)限中可執(zhí)行位被設(shè)置
2、rwSrr- 表示SUID被設(shè)置,但所有者權(quán)限中可執(zhí)行位沒(méi)有被設(shè)置
3、-rwxr-sr-x 表示SGID和同組用戶(hù)權(quán)限中可執(zhí)行位被設(shè)置
4、rw-r-Sr- 表示SGID被設(shè)置,但同組用戶(hù)權(quán)限中可執(zhí)行位沒(méi)有被社
其實(shí)在UNIX的實(shí)現(xiàn)中,文件權(quán)限用12個(gè)二進(jìn)制位表示,如果該位置上的值是
1,表示有相應(yīng)的權(quán)限:
11 10 9 8 7 6 5 4 3 2 1 0
S G T r w x r w x r w x
第11位為SUID位,第10位為SGID位,第9位為sticky位,第8-0位對(duì)應(yīng)于上面的三組rwx位。
11 10 9 8 7 6 5 4 3 2 1 0
上面的-rwsr-xr-x的值為: 1 0 0 1 1 1 1 0 1 1 0 1
rw-r-Sr-的值為: 0 1 0 1 1 0 1 0 0 1 0 0
給文件加SUID和SUID的命令如下:
chmod u+s filename 設(shè)置SUID位
chmod u-s filename 去掉SUID設(shè)置
chmod g+s filename 設(shè)置SGID位
chmod g-s filename 去掉SGID設(shè)置
另外一種方法是chmod命令用八進(jìn)制表示方法的設(shè)置。如果明白了前面的12位權(quán)限表示法也很簡(jiǎn)單。
二、SUID和SGID的詳細(xì)解析
由于SUID和SGID是在執(zhí)行程序(程序的可執(zhí)行位被設(shè)置)時(shí)起作用,而可執(zhí)行位只對(duì)普通文件和目錄文件有意義,所以設(shè)置其他種類(lèi)文件的SUID和SGID位是沒(méi)有多大意義的。
首先講普通文件的SUID和SGID的作用。例子:
如果普通文件myfile是屬于foo用戶(hù)的,是可執(zhí)行的,現(xiàn)在沒(méi)設(shè)SUID位,ls命令顯示如下:
-rwxr-xr-x 1 foo staff 7734 Apr 05 17:07 myfile任何用戶(hù)都可以執(zhí)行這個(gè)程序。UNIX的內(nèi)核是根據(jù)什么來(lái)確定一個(gè)進(jìn)程對(duì)資源的訪問(wèn)權(quán)限的呢?是這個(gè)進(jìn)程的運(yùn)行用戶(hù)的(有效)ID,包括 user id和group id。用戶(hù)可以用id命令來(lái)查到自己的或其他用戶(hù)的user id和group id。
除了一般的user id 和group id外,還有兩個(gè)稱(chēng)之為effective 的id,就是有效id,上面的四個(gè)id表示為:uid,gid,euid,egid。內(nèi)核主要是根據(jù)euid和egid來(lái)確定進(jìn)程對(duì)資源的訪問(wèn)權(quán)限。
一個(gè)進(jìn)程如果沒(méi)有SUID或SGID位,則euid=uid egid=gid,分別是運(yùn)行這個(gè)程序的用戶(hù)的uid和gid。例如kevin用戶(hù)的uid和gid分別為204和202,foo用戶(hù)的uid和gid為 200,201,kevin運(yùn)行myfile程序形成的進(jìn)程的euid=uid=204,egid=gid=202,內(nèi)核根據(jù)這些值來(lái)判斷進(jìn)程對(duì)資源訪問(wèn) 的限制,其實(shí)就是kevin用戶(hù)對(duì)資源訪問(wèn)的權(quán)限,和foo沒(méi)關(guān)系。
如果一個(gè)程序設(shè)置了SUID,則euid和egid變成被運(yùn)行的程序的所有者的uid和gid,例如kevin用戶(hù)運(yùn)行myfile,euid=200,egid=201,uid=204,gid=202,則這個(gè)進(jìn)程具有它的屬主foo的資源訪問(wèn)權(quán)限。
SUID的作用就是這樣:讓本來(lái)沒(méi)有相應(yīng)權(quán)限的用戶(hù)運(yùn)行這個(gè)程序時(shí),可以訪問(wèn)他沒(méi)有權(quán)限訪問(wèn)的資源。passwd就是一個(gè)很鮮明的例子。
SUID的優(yōu)先級(jí)比SGID高,當(dāng)一個(gè)可執(zhí)行程序設(shè)置了SUID,則SGID會(huì)自動(dòng)變成相應(yīng)的egid。
下面討論一個(gè)例子:
UNIX系統(tǒng)有一個(gè)/dev/kmem的設(shè)備文件,是一個(gè)字符設(shè)備文件,里面存儲(chǔ)了核心程序要訪問(wèn)的數(shù)據(jù),包括用戶(hù)的口令。所以這個(gè)文件不能給一般的用戶(hù)讀寫(xiě),權(quán)限設(shè)為:cr-r---- 1 root system 2, 1 May 25 1998 kmem
但ps等程序要讀這個(gè)文件,而ps的權(quán)限設(shè)置如下:
-r-xr-sr-x 1 bin system 59346 Apr 05 1998 ps
這是一個(gè)設(shè)置了SGID的程序,而ps的用戶(hù)是bin,不是root,所以不能設(shè)置SUID來(lái)訪問(wèn)kmem,但大家注意了,bin和root 都屬于system組,而且ps設(shè)置了SGID,一般用戶(hù)執(zhí)行ps,就會(huì)獲得system組用戶(hù)的權(quán)限,而文件kmem的同組用戶(hù)的權(quán)限是可讀,所以一般 用戶(hù)執(zhí)行ps就沒(méi)問(wèn)題了。但有些人說(shuō),為什么不把ps程序設(shè)置為root用戶(hù)的程序,然后設(shè)置SUID位,不也行嗎?這的確可以解決問(wèn)題,但實(shí)際中為什么 不這樣做呢?因?yàn)镾GID的風(fēng)險(xiǎn)比SUID小得多,所以出于系統(tǒng)安全的考慮,應(yīng)該盡量用SGID代替SUID的程序,如果可能的話。下面來(lái)說(shuō)明一下 SGID對(duì)目錄的影響。SUID對(duì)目錄沒(méi)有影響。如果一個(gè)目錄設(shè)置了SGID位,那么如果任何一個(gè)用戶(hù)對(duì)這個(gè)目錄有寫(xiě)權(quán)限的話,他在這個(gè)目錄所建立的文件 的組都會(huì)自動(dòng)轉(zhuǎn)為這個(gè)目錄的屬主所在的組,而文件所有者不變,還是屬于建立這個(gè)文件的用戶(hù)。
三、關(guān)于SUID和SGID的編程
和SUID和SGID編程比較密切相關(guān)的有以下的頭文件和函數(shù):
#include
#include
uid_t getuid(void);
uid_t geteuid(void);
gid_t getgid (void);
gid_t getegid (void);
int setuid (uid_t UID);
int setruid (uid_t RUID);
int seteuid (uid_t EUID);
int setreuid (uid_t RUID,uid_t EUID);
int setgid (gid_t GID);
int setrgid (gid_t RGID);
int setegid (git_t EGID);
int setregid (gid_t RGID, gid_t EGID);
具體這些函數(shù)的說(shuō)明在這里就不詳細(xì)列出來(lái)了,要用到的可以用man查。
SUID/SGID :
假如你有文件a.txt
#ls -l a.txt
-rwxrwxrwx
#chmod 4777 a.txt
-rwsrwxrwx ======>注意s位置
#chmod 2777 a.txt
-rwxrwsrwx ======>注意s位置
#chmod 7777 a.txt
-rwsrwxswt ======>出現(xiàn)了t,t的作用在內(nèi)存中盡量保存a.txt,節(jié)省系統(tǒng)再加載的時(shí)間.
現(xiàn)在再看前面設(shè)置 SUID/SGID作用:
#cd /sbin
#./lsusb
...
#su aaa(普通用戶(hù))
$./lsusb
...
是不是現(xiàn)在顯示出錯(cuò)?
$su
#chmod 4755 lsusb
#su aaa
$./lsusb
... 現(xiàn)在明白了嗎?本來(lái)是只有root用戶(hù)才能執(zhí)行的命令,加了SUID后,普通用戶(hù)就可以像root一樣的用,權(quán)限提升了。上面是對(duì)于文件來(lái)說(shuō)的,對(duì)于目錄也差不多!
目錄的S屬性使得在該目錄下創(chuàng)建的任何文件及子目錄屬于該目錄所擁有的組,目錄的T屬性使得該目錄的所有者及root才能刪除該目錄。還有對(duì) 于s與S,設(shè)置SUID/SGID需要有運(yùn)行權(quán)限,否則用ls -l后就會(huì)看到S,證明你所設(shè)置的SUID/SGID沒(méi)有起作用。
Why we need suid,how do we use suid?
r -- 讀訪問(wèn)
w -- 寫(xiě)訪問(wèn)
x -- 執(zhí)行許可
s -- SUID/SGID
t -- sticky位
那么 suid/sgid是做什么的? 為什么會(huì)有suid位呢?
要想明白這個(gè),先讓我們看個(gè)問(wèn)題:如果讓每個(gè)用戶(hù)更改自己的密碼?
用戶(hù)修改密碼,是通過(guò)運(yùn)行命令passwd來(lái)實(shí)現(xiàn)的。最終必須要修改/etc/passwd文件,而passwd的文件的屬性是:
#ls -l /etc/passwd
rw-rr- 1 root root 2520 Jul 12 18:25 passwd
我們可以看到passwd文件只有對(duì)于root用戶(hù)是可寫(xiě)的,而對(duì)于所有的他用戶(hù)來(lái)說(shuō)都是沒(méi)有寫(xiě)權(quán)限的。 那么一個(gè)普通的用戶(hù)如何能夠通過(guò)運(yùn)行passwd命令修改這個(gè)passwd文件呢?
為了解決這個(gè)問(wèn)題,SUID/SGID便應(yīng)運(yùn)而生。而且AT&T對(duì)它申請(qǐng)了專(zhuān)利。 呵呵。
SUID和SGID是如何解決這個(gè)問(wèn)題呢?
首先,我們要知道一點(diǎn):進(jìn)程在運(yùn)行的時(shí)候,有一些屬性,其中包括 實(shí)際用戶(hù)ID,實(shí)際組ID,有效用戶(hù)ID,有效組ID等。 實(shí)際用戶(hù)ID和實(shí)際組ID標(biāo)識(shí)我們是誰(shuí),誰(shuí)在運(yùn)行這個(gè)程序,一般這2個(gè)字段在登陸時(shí)決定,在一個(gè)登陸會(huì)話期間, 這些值基本上不改變。
而有效用戶(hù)ID和有效組ID則決定了進(jìn)程在運(yùn)行時(shí)的權(quán)限。內(nèi)核在決定進(jìn)程是否有文件存取權(quán)限時(shí),是采用了進(jìn)程的有效用戶(hù)ID來(lái)進(jìn)行判斷的。
知道了這點(diǎn),我們來(lái)看看SUID的解決途徑:
當(dāng)一個(gè)程序設(shè)置了為SUID位時(shí),內(nèi)核就知道了運(yùn)行這個(gè)程序的時(shí)候,應(yīng)該認(rèn)為是文件的所有者在運(yùn)行這個(gè)程序。即該程序運(yùn)行的時(shí)候,有效用戶(hù)ID是該程序的所有者。舉個(gè)例子:
[root@sgrid5 bin]# ls -l passwd
-r-s-s-x 1 root root 16336 Feb 14 2003 passwd
雖然你以test登陸系統(tǒng),但是當(dāng)你輸入passwd命令來(lái)更改密碼的時(shí)候,由于passwd設(shè)置了SUID位,因此雖然進(jìn)程的實(shí)際用戶(hù)ID 是test對(duì)應(yīng)的ID,但是進(jìn)程的有效用戶(hù)ID則是passwd文件的所有者root的ID,因此可以修改/etc/passwd文件。
讓我們看另外一個(gè)例子。
ping命令應(yīng)用廣泛,可以測(cè)試網(wǎng)絡(luò)是否連接正常。ping在運(yùn)行中是采用了ICMP協(xié)議,需要發(fā)送ICMP報(bào)文。但是只有root用戶(hù)才能建立ICMP報(bào)文,如何解決這個(gè)問(wèn)題呢?同樣,也是通過(guò)SUID位來(lái)解決。
[root@sgrid5 bin]# ls -l /bin/ping
-rwsr-sr-x 1 root root 28628 Jan 25 2003 /bin/ping
我們可以測(cè)試一下,如果去掉ping的SUID位,再用普通用戶(hù)去運(yùn)行命令,看會(huì)怎么樣。
[root@sgrid5 bin]#chmod u-s /bin/ping
[root@sgrid5 bin]# ls -l ping
-rwxr-xr-x 1 root root 28628 Jan 25 2003 ping
[root@sgrid5 bin]#su test
[test@sgrid5 bin]$ ping byhh.net
ping: icmp open socket: Operation not permitted
SUID雖然很好了解決了一些問(wèn)題,但是同時(shí)也會(huì)帶來(lái)一些安全隱患。
因?yàn)樵O(shè)置了 SUID 位的程序如果被攻擊(通過(guò)緩沖區(qū)溢出等方面),那么hacker就可以拿到root權(quán)限。
因此在安全方面特別要注意那些設(shè)置了SUID的程序。
通過(guò)以下的命令可以找到系統(tǒng)上所有的設(shè)置了suid的文件:
[root@sgrid5 /]# find / -perm -04000 -type f -ls
對(duì)于這里為什么是4000,大家可以看一下前面的st_mode的各bit的意義就明白了。
在這些設(shè)置了suid的程序里,如果用不上的,就最好取消該程序的suid位。
總結(jié):
1.Set UID:當(dāng)文件系統(tǒng)的"所有者權(quán)限組合"的可執(zhí)行位被s(即rws------)取代時(shí),構(gòu)成特殊權(quán)限規(guī)定Set UID,簡(jiǎn)稱(chēng)SUID。僅對(duì)系統(tǒng)中的二進(jìn)制可執(zhí)行文件設(shè)置有效,而且不可對(duì)Shell Script施加設(shè)置。
2.Set GID:當(dāng)所有者所在的用戶(hù)組(group)的權(quán)限組合中可執(zhí)行位被s所取代時(shí)(例如--
3.Sticky Bit:當(dāng)文件系統(tǒng)"其他(others)"的權(quán)限組合中可執(zhí)行位被t所取代時(shí)(例如------rwt),便構(gòu)成Sticky Bit的權(quán)限設(shè)置。它只對(duì)目錄有效。
SUID和SGID,主要作用是用于當(dāng)非某個(gè)文件的所有者(或組)執(zhí)行(或操作目錄)文件時(shí),可以暫時(shí)獲得該文件所有者的權(quán)限。
SBIT的作用在于訪問(wèn)控制,當(dāng)它對(duì)某個(gè)目錄設(shè)置此屬性后,該目錄下的所有文件,即使其它人有w屬性,都不得對(duì)其更名、移動(dòng)、刪除。
設(shè)置方法:
如果你已經(jīng)掌握了用(八進(jìn)制)數(shù)字來(lái)表示權(quán)限的規(guī)則,再結(jié)合chmod命令進(jìn)行設(shè)置就很簡(jiǎn)單了。以下是SUID/SGID/Sticky Bit約定對(duì)應(yīng)的八進(jìn)制數(shù)值:
SUID = 4
SGID = 2
SBIT = 1
設(shè)置時(shí)我們把表示特殊權(quán)限的數(shù)字放在其他三位數(shù)字權(quán)限的前面。
這里指出了jar包的典型的目錄結(jié)構(gòu)。簡(jiǎn)單翻譯:
META-INF目錄中的下列文件和目錄獲得Java 2平臺(tái)的認(rèn)可與解釋?zhuān)脕?lái)配置應(yīng)用程序、擴(kuò)展程序、類(lèi)加載器和服務(wù):
• MANIFEST.MF:清單文件,用來(lái)定義與擴(kuò)展和數(shù)據(jù)包相關(guān)的數(shù)據(jù)。
• INDEX.LIST:這個(gè)文件由JAR工具的新“-i”選項(xiàng)生成,其中包含在一個(gè)應(yīng)用程序或擴(kuò)展中定義的數(shù)據(jù)包的地址信息。它是JarIndex的一部分,被類(lèi)加載器用來(lái)加速類(lèi)加載過(guò)程。
• x.SF:JAR文件的簽名文件。x代表基礎(chǔ)文件名。
• x.DSA:這個(gè)簽名塊文件與同名基礎(chǔ)簽名文件有關(guān)。此文件存儲(chǔ)對(duì)應(yīng)簽名文件的數(shù)字簽名。
• services/:這個(gè)目錄存儲(chǔ)所有服務(wù)提供程序配置文件。
介紹:
在META-INF/services目錄下保存的是service provider的配置文件。 服務(wù)在應(yīng)用中會(huì)是一個(gè)接口(更多的是抽象類(lèi))。
一個(gè)類(lèi)服務(wù)器提供者實(shí)現(xiàn)了一個(gè)服務(wù)類(lèi)。這類(lèi)的服務(wù)提供類(lèi)可以以擴(kuò)展的形式發(fā)布到平臺(tái)上。所以,jar文件引入了擴(kuò)展目錄,同樣你也可以將服務(wù)提供者加入classpath提供訪問(wèn)。
服務(wù)都是表現(xiàn)為一個(gè)積累,而一個(gè)服務(wù)提供者通常是集成或?qū)崿F(xiàn)了服務(wù)定義類(lèi)。服務(wù)提供類(lèi)通常不會(huì)像代理類(lèi)一樣為了正常提供服務(wù)而包含了請(qǐng)求者的許多信息。服務(wù)提供類(lèi)一般傾向于高集成。
對(duì)這類(lèi)服務(wù)提供類(lèi)的唯一強(qiáng)制性要求就是必須有一個(gè)無(wú)參的構(gòu)造函數(shù)。
provider 配置文件
META-INF/services目錄作為provider配置文件的存放路徑。provider配置文件中必須是全類(lèi)名(包含package)。配置文件可以存在space tab 換行等字符,#作為注釋。
注意:provider配置文件必須是以UTF-8編碼。
總結(jié):
service provider機(jī)制為程序的動(dòng)態(tài)擴(kuò)展提供了契機(jī),在應(yīng)用中你可以針對(duì)接口編程,通過(guò)RTTI技術(shù)可以比較完美的解決程序之間的耦合性。相比于spring DIP機(jī)制,這也是一個(gè)不錯(cuò)的嘗試,至少它不需要耦合spring包。
fstab中存放了與分區(qū)有關(guān)的重要信息,其中每一行為一個(gè)分區(qū)記錄,每一行又可分為六個(gè)部份:
1. 第一項(xiàng)是您想要mount的儲(chǔ)存裝置的實(shí)體位置,如/dev/sda6分區(qū) (分區(qū)或卷標(biāo)名)
2. 第二項(xiàng)就是您想要將其加入至哪個(gè)目錄位置,如/home或/, (掛載點(diǎn) )
3. 第三項(xiàng)就是所謂的local filesystem,其包含了以下格式:如ext、ext2、msdos、iso9660、nfs、swap等,或如ext2 (文件系統(tǒng))
4. 第四項(xiàng)就是您mount時(shí),所要設(shè)定的狀態(tài),如ro(只讀)或defaults(包括了其它參數(shù)如rw、suid、exec、auto、nouser、async),可以參見(jiàn)「mount nfs」。 (讀寫(xiě)狀態(tài))
5. 第五項(xiàng)是提供DUMP功能,在系統(tǒng)DUMP時(shí)是否需要BACKUP的標(biāo)志位,其內(nèi)定值是0。 (0為不備份,1為要備份,一般根分區(qū)要備份)
6. 第六項(xiàng)是設(shè)定是否要在開(kāi)機(jī)時(shí)做check的動(dòng)作,除了其必要的check為1之外,其它皆可視需要設(shè)定,內(nèi)定值是0。 (0為不自檢,1或者2為要自檢,如果是根分區(qū)要設(shè)為1,其他分區(qū)只能是2)