liunx ssh命令詳解
我們將開始學(xué)習(xí)如何構(gòu)建一個(gè)Git服務(wù)器,如何在具體的事件中寫一個(gè)針對(duì)特定的觸發(fā)操作的自定義Git(例如通告),如何發(fā)布你的代碼到一個(gè)網(wǎng)站。接下來(lái)是小編為大家收集的liunx ssh命令詳解,歡迎大家閱讀:
liunx ssh命令詳解
目前為止,用戶對(duì)Git的焦點(diǎn)主要在Git的使用上。這篇文章中,我將論述如何管理Git以及自定Git架構(gòu)的設(shè)計(jì)。你可能會(huì)覺(jué)得這聽起來(lái)像“先進(jìn)的Git技術(shù)”或者“如果你是學(xué)霸讀這篇文章”的委婉說(shuō)法,但是事實(shí)上理解Git如何工作不需要任何的高深知識(shí)或者專業(yè)培訓(xùn),在一些情況下只需要了解一點(diǎn)Linux。分享Git服務(wù)
創(chuàng)建自己的Git服務(wù)共享非常簡(jiǎn)單, 在許多情況下值得去創(chuàng)建這樣一個(gè)Git服務(wù)。它不僅保證你隨時(shí)可以訪問(wèn)你的代碼,它的無(wú)限制數(shù)據(jù)存儲(chǔ)、持續(xù)集成跟部署同時(shí)為個(gè)人Git管理打開了一道Git延伸與拓展的大門。
假如你知道如何使用Git和SSH,那么你已經(jīng)知道如何創(chuàng)建一個(gè)Git服務(wù)器了。設(shè)計(jì)Git的方式,你創(chuàng)建或者克隆一個(gè)倉(cāng)庫(kù)時(shí),你已經(jīng)創(chuàng)建了一半服務(wù)器。使能SSH訪問(wèn)倉(cāng)庫(kù),并且任何訪問(wèn)你倉(cāng)庫(kù)的人都可以使用你的回購(gòu)協(xié)議作為一個(gè)新克隆的基礎(chǔ)。
但是,會(huì)有一個(gè)小特設(shè)。有些計(jì)劃你可以構(gòu)建關(guān)于同樣數(shù)量的精心設(shè)計(jì)的Git服務(wù)器,但是可以具有更好擴(kuò)展性。
首先是:識(shí)別你的用戶,包括閑雜與未來(lái)的。假如你是唯一用戶,那么無(wú)需任何改變,但是如果你邀請(qǐng)國(guó)外的貢獻(xiàn)者了,那么你應(yīng)該為開發(fā)者搭建一個(gè)貢獻(xiàn)共享系統(tǒng)平臺(tái)。
假定你有一個(gè)可用的服務(wù)器(如果不是,Git無(wú)法解決這個(gè)問(wèn)題,但是運(yùn)行在Raspberry Pi 3 的CentOS將會(huì)是一個(gè)良好開端),第一步是采用SSH鍵值授權(quán)登錄,它比密碼登錄更加強(qiáng)大,因?yàn)樗苊庖哂谛U力攻擊,并且可以避免用戶盡可能簡(jiǎn)單地刪除它們的鍵值。
在你啟用了SSH密鑰認(rèn)證之后,就創(chuàng)建一個(gè) gituser用戶。這是一個(gè)提供給所有通過(guò)了認(rèn)證的用戶的共享用戶賬號(hào):
1$ su -c 'adduser gituser'
然后切換到這個(gè)用戶,并使用合適的權(quán)限創(chuàng)建一個(gè) ~/.ssh 框架。這非常重要,因?yàn)槿绻麢?quán)限設(shè)置太過(guò)于隨意,你自己針對(duì)SSH的防護(hù)默認(rèn)就會(huì)失效。
1$ su - gituser
2$ mkdir .ssh && chmod 700 .ssh
3$ touch .ssh/authorized_keys
4$ chmod 600 .ssh/authorized_keys
authorized_keys 文件里面有所有你賦予其權(quán)限操作你的Git工程的開發(fā)者的SSH公共密鑰。你的開發(fā)者必須創(chuàng)建屬于他們自己的SSH密鑰并將其中的公共密鑰發(fā)送給你。要把這些公共密鑰復(fù)制到gituser的 authorized_keys 文件中去。例如,對(duì)于一個(gè)叫做Bob的開發(fā)者,可以運(yùn)行這些命令:
1$ cat ~/path/to/id_rsa.bob.pub >> \
2/home/gituser/.ssh/authorized_keys
當(dāng)開發(fā)者Bob持有能匹配他發(fā)送給你的公共密鑰的私有密鑰時(shí),他就能以gituser訪問(wèn)服務(wù)器。
不過(guò),你并不會(huì)真的想讓你的開發(fā)者訪問(wèn)到服務(wù)器,即使只是以gituser用戶來(lái)進(jìn)行訪問(wèn)。你想要的是讓他們只能訪問(wèn)到Git資源庫(kù)。因?yàn)檫@個(gè)原因,Git提供了一個(gè)受限的shell,恰如其分的將其稱為 git-shell、以root用戶運(yùn)行下面的這些命令可以將git-shell添加到你的系統(tǒng)中,并使其成為gituser用戶的默認(rèn)shell:
1# grep git-shell /etc/shells || su -c \
2"echo `which git-shell` >> /etc/shells"
3# su -c 'usermod -s git-shell gituser'
現(xiàn)在gituser只能使用SSH來(lái)向Git資源庫(kù)進(jìn)行推送和拉取操作,而不能訪問(wèn)到一個(gè)登陸shell。你應(yīng)該將你自己加入gituser對(duì)應(yīng)的用戶組,在我們的示例服務(wù)器中它還是gituser。
例如:
1# usermod -a -G gituser seth
剩下的唯一一個(gè)步驟就是創(chuàng)建一個(gè)Git資源庫(kù)。因?yàn)椴粫?huì)有人在服務(wù)器上跟它進(jìn)行直接交互(也就是說(shuō)你不會(huì)通過(guò)SSH連上服務(wù)器然后直接在資源庫(kù)中進(jìn)行操作), 這使其成為了一個(gè)基礎(chǔ)的資源庫(kù)。如果你想要把服務(wù)器上的資源庫(kù)用起來(lái),就要將其從它所在的地方克隆到自己的home目錄中去。
嚴(yán)格來(lái)說(shuō),你并不用使其成為一個(gè)基礎(chǔ)資源庫(kù),它還是可以作為一個(gè)普通的資源庫(kù)來(lái)操作的。不過(guò),一個(gè)基礎(chǔ)資源庫(kù)是沒(méi)有*工作樹(working tree)* (也就是說(shuō),不會(huì)有分支會(huì)處在”checkout“狀態(tài))。這很重要,因?yàn)檫h(yuǎn)程用戶不會(huì)被允許向一個(gè)活動(dòng)分支進(jìn)行推送 (你是不會(huì)想在一個(gè)”dev“分支工作時(shí)突然有人將變更推送到你的工作空間的?)。因?yàn)榛A(chǔ)資源庫(kù)不能有活動(dòng)分支,那就不會(huì)有問(wèn)題發(fā)生了。
你可以將資源庫(kù)放到任何你想要放置的地方, 只要你想賦予權(quán)限的用戶和組也能訪問(wèn)到它就行了。你不會(huì)想將目錄存儲(chǔ)到一個(gè)用戶的home目錄的,因?yàn)檫@里的權(quán)限相當(dāng)?shù)貒?yán)格, 而是要放在一個(gè)通用共享的位置,例如 /opt or /usr/local/share.
以root用戶創(chuàng)建一個(gè)基礎(chǔ)資源庫(kù):
1# git init --bare /opt/jupiter.git
2# chown -R gituser:gituser /opt/jupiter.git
3# chmod -R 770 /opt/jupiter.git
現(xiàn)在任何已gituser認(rèn)證的、或者是位于gituser分組的用戶都可以讀取和寫入jupiter.git資源庫(kù)。你可以在自己本機(jī)上試試看:
1$ git clone gituser@example.com:/opt/jupiter.git jupiter.clone
2Cloning into 'jupiter.clone'...
3Warning: you appear to have cloned an empty repository.
記?。洪_發(fā)有必須讓他們的公共SSH密鑰導(dǎo)入gituser用戶的 authorized_keys 文件, 或者是擁有服務(wù)器上面的賬戶(就像你一樣), 那樣的話他們就必須是gituser組的成員。
Git鉤子
運(yùn)行你自己的Git服務(wù)器帶來(lái)的一個(gè)好處是它提供了Git鉤子。Git托管服務(wù)有時(shí)也提供了一個(gè)類似鉤子的接口,但那并不是真正的可以訪問(wèn)文件系統(tǒng)的Git鉤子。一個(gè)Git鉤子是一個(gè)腳本,它在Git進(jìn)程中的某個(gè)時(shí)刻執(zhí)行。在一個(gè)倉(cāng)庫(kù)(repository)接受一個(gè)提交(commit)之前,或者收到一個(gè)提交之后,或者接收一個(gè)推送(push)之前,或者收到一個(gè)推送之后等時(shí)刻執(zhí)行一個(gè)鉤子。
這個(gè)系統(tǒng)很簡(jiǎn)單:任何可執(zhí)行的腳本都存放在.git/hooks目錄中,使用標(biāo)準(zhǔn)的命名方案,并且在某個(gè)指定的時(shí)刻執(zhí)行。腳本執(zhí)行的時(shí)間由名字來(lái)決定;pre-push腳本在推送之前執(zhí)行,post-receive腳本在收到一個(gè)提交之后執(zhí)行,諸如此類。它基本上屬于自文檔(self-documenting)。
可以使用任何語(yǔ)言編寫鉤子腳本;如果你能在你的系統(tǒng)上運(yùn)行某種語(yǔ)言的hello world腳本,那么你就可以使用那門語(yǔ)言來(lái)編寫Git鉤子腳本。默認(rèn)情況下,Git附帶了一些范例,但沒(méi)有啟用。
想要運(yùn)行一個(gè)腳本嗎?使用起來(lái)很簡(jiǎn)單。如果你還沒(méi)有Git倉(cāng)庫(kù)的話,首先創(chuàng)建一個(gè)。
1$ mkdir jupiter
2$ cd jupiter
3$ git init .
然后編寫一個(gè)"hello world" Git鉤子。由于在工作中我為了傳統(tǒng)支持而使用tcsh,所以我堅(jiān)持使用它作為我的腳本語(yǔ)言,但你可以自由地選用你喜愛(ài)的語(yǔ)言(Bash、Python、Ruby、Perl、Rust、Swift、Go):
1$ echo "#\!/bin/tcsh" > .git/hooks/post-commit
2$ echo "echo 'POST-COMMIT SCRIPT TRIGGERED'" > \
3~/jupiter/.git/hooks/post-commit
4$ chmod +x ~/jupiter/.git/hooks/post-commit
現(xiàn)在進(jìn)行測(cè)試:
1$ echo "hello world" > foo.txt
2$ git add foo.txt
3$ git commit -m 'first commit'
4! POST-COMMIT SCRIPT TRIGGERED
5[master (root-commit) c8678e0] first commit
61 file changed, 1 insertion(+)
7create mode 100644 foo.txt
這就是你的第一個(gè)可以正常運(yùn)行的Git鉤子。
著名的推送到web 鉤子
一個(gè)流行的Git鉤子用法是自動(dòng)推送改變部分到工作生產(chǎn)中的web服務(wù)器目錄。這是一個(gè)偉大構(gòu)建FTP的方式,保留開發(fā)環(huán)節(jié)的全版本控制,并且整合、自動(dòng)化發(fā)布內(nèi)容。
如果正確執(zhí)行,它將會(huì)工作運(yùn)行良好,在某一種程度來(lái)說(shuō),一直應(yīng)該做的是考慮如何網(wǎng)絡(luò)發(fā)布。它是不錯(cuò)的。我不知道最初是誰(shuí)想出這主意的,但是我第一次是從EMacs和來(lái)自IBM公司的Git-mentor、Bill Von Hagen那里聽到的。他的文章仍然是對(duì)這個(gè)過(guò)程起決定性作用的介紹:Git 改變分布式Web開發(fā)規(guī)則。
Git變量
每個(gè)Git鉤子獲取一組不同的Git動(dòng)作觸發(fā)它的相關(guān)變量。你可能會(huì)用到這些變量,也可能用不到。這取決于你所寫的作品。 如果你想要的是一個(gè)普通的郵件來(lái)通知你,有人推了東西。那么你不需要細(xì)節(jié),也不需要腳本,因?yàn)槟憧梢蕴子矛F(xiàn)有的樣板。如果你想在郵件里瀏覽別人提交的信息和作者,那么對(duì)你的腳本要求更高。
Git鉤子并不是用戶直接運(yùn)行的,所以要理解透如何獲取這些混亂卻重要的信息。事實(shí)上,一個(gè)Git鉤子腳本與其他任何腳本類似,像BASH、Python、C++或者其他腳本一樣的方式接受來(lái)自stdin的參數(shù)。不同的是,我們不會(huì)提供自己入?yún)?,所以使用它時(shí)要弄清楚你想要的是什么(參數(shù))。
編寫一個(gè)Git鉤子之前,可以進(jìn)入到你的項(xiàng)目目錄.git/hooks查看Git提供的范例。例如,下面是pre-push.sample文件的注釋部分:
1# class="main">
liunx ssh命令詳解
2#
我們將開始學(xué)習(xí)如何構(gòu)建一個(gè)Git服務(wù)器,如何在具體的事件中寫一個(gè)針對(duì)特定的觸發(fā)操作的自定義Git(例如通告),如何發(fā)布你的代碼到一個(gè)網(wǎng)站。接下來(lái)是小編為大家收集的liunx ssh命令詳解,歡迎大家閱讀:
liunx ssh命令詳解
目前為止,用戶對(duì)Git的焦點(diǎn)主要在Git的使用上。這篇文章中,我將論述如何管理Git以及自定Git架構(gòu)的設(shè)計(jì)。你可能會(huì)覺(jué)得這聽起來(lái)像“先進(jìn)的Git技術(shù)”或者“如果你是學(xué)霸讀這篇文章”的委婉說(shuō)法,但是事實(shí)上理解Git如何工作不需要任何的高深知識(shí)或者專業(yè)培訓(xùn),在一些情況下只需要了解一點(diǎn)Linux。分享Git服務(wù)
創(chuàng)建自己的Git服務(wù)共享非常簡(jiǎn)單, 在許多情況下值得去創(chuàng)建這樣一個(gè)Git服務(wù)。它不僅保證你隨時(shí)可以訪問(wèn)你的代碼,它的無(wú)限制數(shù)據(jù)存儲(chǔ)、持續(xù)集成跟部署同時(shí)為個(gè)人Git管理打開了一道Git延伸與拓展的大門。
假如你知道如何使用Git和SSH,那么你已經(jīng)知道如何創(chuàng)建一個(gè)Git服務(wù)器了。設(shè)計(jì)Git的方式,你創(chuàng)建或者克隆一個(gè)倉(cāng)庫(kù)時(shí),你已經(jīng)創(chuàng)建了一半服務(wù)器。使能SSH訪問(wèn)倉(cāng)庫(kù),并且任何訪問(wèn)你倉(cāng)庫(kù)的人都可以使用你的回購(gòu)協(xié)議作為一個(gè)新克隆的基礎(chǔ)。
但是,會(huì)有一個(gè)小特設(shè)。有些計(jì)劃你可以構(gòu)建關(guān)于同樣數(shù)量的精心設(shè)計(jì)的Git服務(wù)器,但是可以具有更好擴(kuò)展性。
首先是:識(shí)別你的用戶,包括閑雜與未來(lái)的。假如你是唯一用戶,那么無(wú)需任何改變,但是如果你邀請(qǐng)國(guó)外的貢獻(xiàn)者了,那么你應(yīng)該為開發(fā)者搭建一個(gè)貢獻(xiàn)共享系統(tǒng)平臺(tái)。
假定你有一個(gè)可用的服務(wù)器(如果不是,Git無(wú)法解決這個(gè)問(wèn)題,但是運(yùn)行在Raspberry Pi 3 的CentOS將會(huì)是一個(gè)良好開端),第一步是采用SSH鍵值授權(quán)登錄,它比密碼登錄更加強(qiáng)大,因?yàn)樗苊庖哂谛U力攻擊,并且可以避免用戶盡可能簡(jiǎn)單地刪除它們的鍵值。
在你啟用了SSH密鑰認(rèn)證之后,就創(chuàng)建一個(gè) gituser用戶。這是一個(gè)提供給所有通過(guò)了認(rèn)證的用戶的共享用戶賬號(hào):
1$ su -c 'adduser gituser'
然后切換到這個(gè)用戶,并使用合適的權(quán)限創(chuàng)建一個(gè) ~/.ssh 框架。這非常重要,因?yàn)槿绻麢?quán)限設(shè)置太過(guò)于隨意,你自己針對(duì)SSH的防護(hù)默認(rèn)就會(huì)失效。
1$ su - gituser
2$ mkdir .ssh && chmod 700 .ssh
3$ touch .ssh/authorized_keys
4$ chmod 600 .ssh/authorized_keys
authorized_keys 文件里面有所有你賦予其權(quán)限操作你的Git工程的開發(fā)者的SSH公共密鑰。你的開發(fā)者必須創(chuàng)建屬于他們自己的SSH密鑰并將其中的公共密鑰發(fā)送給你。要把這些公共密鑰復(fù)制到gituser的 authorized_keys 文件中去。例如,對(duì)于一個(gè)叫做Bob的開發(fā)者,可以運(yùn)行這些命令:
1$ cat ~/path/to/id_rsa.bob.pub >> \
2/home/gituser/.ssh/authorized_keys
當(dāng)開發(fā)者Bob持有能匹配他發(fā)送給你的公共密鑰的私有密鑰時(shí),他就能以gituser訪問(wèn)服務(wù)器。
不過(guò),你并不會(huì)真的想讓你的開發(fā)者訪問(wèn)到服務(wù)器,即使只是以gituser用戶來(lái)進(jìn)行訪問(wèn)。你想要的是讓他們只能訪問(wèn)到Git資源庫(kù)。因?yàn)檫@個(gè)原因,Git提供了一個(gè)受限的shell,恰如其分的將其稱為 git-shell、以root用戶運(yùn)行下面的這些命令可以將git-shell添加到你的系統(tǒng)中,并使其成為gituser用戶的默認(rèn)shell:
1# grep git-shell /etc/shells || su -c \
2"echo `which git-shell` >> /etc/shells"
3# su -c 'usermod -s git-shell gituser'
現(xiàn)在gituser只能使用SSH來(lái)向Git資源庫(kù)進(jìn)行推送和拉取操作,而不能訪問(wèn)到一個(gè)登陸shell。你應(yīng)該將你自己加入gituser對(duì)應(yīng)的用戶組,在我們的示例服務(wù)器中它還是gituser。
例如:
1# usermod -a -G gituser seth
剩下的唯一一個(gè)步驟就是創(chuàng)建一個(gè)Git資源庫(kù)。因?yàn)椴粫?huì)有人在服務(wù)器上跟它進(jìn)行直接交互(也就是說(shuō)你不會(huì)通過(guò)SSH連上服務(wù)器然后直接在資源庫(kù)中進(jìn)行操作), 這使其成為了一個(gè)基礎(chǔ)的資源庫(kù)。如果你想要把服務(wù)器上的資源庫(kù)用起來(lái),就要將其從它所在的地方克隆到自己的home目錄中去。
嚴(yán)格來(lái)說(shuō),你并不用使其成為一個(gè)基礎(chǔ)資源庫(kù),它還是可以作為一個(gè)普通的資源庫(kù)來(lái)操作的。不過(guò),一個(gè)基礎(chǔ)資源庫(kù)是沒(méi)有*工作樹(working tree)* (也就是說(shuō),不會(huì)有分支會(huì)處在”checkout“狀態(tài))。這很重要,因?yàn)檫h(yuǎn)程用戶不會(huì)被允許向一個(gè)活動(dòng)分支進(jìn)行推送 (你是不會(huì)想在一個(gè)”dev“分支工作時(shí)突然有人將變更推送到你的工作空間的?)。因?yàn)榛A(chǔ)資源庫(kù)不能有活動(dòng)分支,那就不會(huì)有問(wèn)題發(fā)生了。
你可以將資源庫(kù)放到任何你想要放置的地方, 只要你想賦予權(quán)限的用戶和組也能訪問(wèn)到它就行了。你不會(huì)想將目錄存儲(chǔ)到一個(gè)用戶的home目錄的,因?yàn)檫@里的權(quán)限相當(dāng)?shù)貒?yán)格, 而是要放在一個(gè)通用共享的位置,例如 /opt or /usr/local/share.
以root用戶創(chuàng)建一個(gè)基礎(chǔ)資源庫(kù):
1# git init --bare /opt/jupiter.git
2# chown -R gituser:gituser /opt/jupiter.git
3# chmod -R 770 /opt/jupiter.git
現(xiàn)在任何已gituser認(rèn)證的、或者是位于gituser分組的用戶都可以讀取和寫入jupiter.git資源庫(kù)。你可以在自己本機(jī)上試試看:
1$ git clone gituser@example.com:/opt/jupiter.git jupiter.clone
2Cloning into 'jupiter.clone'...
3Warning: you appear to have cloned an empty repository.
記住:開發(fā)有必須讓他們的公共SSH密鑰導(dǎo)入gituser用戶的 authorized_keys 文件, 或者是擁有服務(wù)器上面的賬戶(就像你一樣), 那樣的話他們就必須是gituser組的成員。
Git鉤子
運(yùn)行你自己的Git服務(wù)器帶來(lái)的一個(gè)好處是它提供了Git鉤子。Git托管服務(wù)有時(shí)也提供了一個(gè)類似鉤子的接口,但那并不是真正的可以訪問(wèn)文件系統(tǒng)的Git鉤子。一個(gè)Git鉤子是一個(gè)腳本,它在Git進(jìn)程中的某個(gè)時(shí)刻執(zhí)行。在一個(gè)倉(cāng)庫(kù)(repository)接受一個(gè)提交(commit)之前,或者收到一個(gè)提交之后,或者接收一個(gè)推送(push)之前,或者收到一個(gè)推送之后等時(shí)刻執(zhí)行一個(gè)鉤子。
這個(gè)系統(tǒng)很簡(jiǎn)單:任何可執(zhí)行的腳本都存放在.git/hooks目錄中,使用標(biāo)準(zhǔn)的命名方案,并且在某個(gè)指定的時(shí)刻執(zhí)行。腳本執(zhí)行的時(shí)間由名字來(lái)決定;pre-push腳本在推送之前執(zhí)行,post-receive腳本在收到一個(gè)提交之后執(zhí)行,諸如此類。它基本上屬于自文檔(self-documenting)。
可以使用任何語(yǔ)言編寫鉤子腳本;如果你能在你的系統(tǒng)上運(yùn)行某種語(yǔ)言的hello world腳本,那么你就可以使用那門語(yǔ)言來(lái)編寫Git鉤子腳本。默認(rèn)情況下,Git附帶了一些范例,但沒(méi)有啟用。
想要運(yùn)行一個(gè)腳本嗎?使用起來(lái)很簡(jiǎn)單。如果你還沒(méi)有Git倉(cāng)庫(kù)的話,首先創(chuàng)建一個(gè)。
1$ mkdir jupiter
2$ cd jupiter
3$ git init .
然后編寫一個(gè)"hello world" Git鉤子。由于在工作中我為了傳統(tǒng)支持而使用tcsh,所以我堅(jiān)持使用它作為我的腳本語(yǔ)言,但你可以自由地選用你喜愛(ài)的語(yǔ)言(Bash、Python、Ruby、Perl、Rust、Swift、Go):
1$ echo "#\!/bin/tcsh" > .git/hooks/post-commit
2$ echo "echo 'POST-COMMIT SCRIPT TRIGGERED'" > \
3~/jupiter/.git/hooks/post-commit
4$ chmod +x ~/jupiter/.git/hooks/post-commit
現(xiàn)在進(jìn)行測(cè)試:
1$ echo "hello world" > foo.txt
2$ git add foo.txt
3$ git commit -m 'first commit'
4! POST-COMMIT SCRIPT TRIGGERED
5[master (root-commit) c8678e0] first commit
61 file changed, 1 insertion(+)
7create mode 100644 foo.txt
這就是你的第一個(gè)可以正常運(yùn)行的Git鉤子。
著名的推送到web 鉤子
一個(gè)流行的Git鉤子用法是自動(dòng)推送改變部分到工作生產(chǎn)中的web服務(wù)器目錄。這是一個(gè)偉大構(gòu)建FTP的方式,保留開發(fā)環(huán)節(jié)的全版本控制,并且整合、自動(dòng)化發(fā)布內(nèi)容。
如果正確執(zhí)行,它將會(huì)工作運(yùn)行良好,在某一種程度來(lái)說(shuō),一直應(yīng)該做的是考慮如何網(wǎng)絡(luò)發(fā)布。它是不錯(cuò)的。我不知道最初是誰(shuí)想出這主意的,但是我第一次是從EMacs和來(lái)自IBM公司的Git-mentor、Bill Von Hagen那里聽到的。他的文章仍然是對(duì)這個(gè)過(guò)程起決定性作用的介紹:Git 改變分布式Web開發(fā)規(guī)則。
Git變量
每個(gè)Git鉤子獲取一組不同的Git動(dòng)作觸發(fā)它的相關(guān)變量。你可能會(huì)用到這些變量,也可能用不到。這取決于你所寫的作品。 如果你想要的是一個(gè)普通的郵件來(lái)通知你,有人推了東西。那么你不需要細(xì)節(jié),也不需要腳本,因?yàn)槟憧梢蕴子矛F(xiàn)有的樣板。如果你想在郵件里瀏覽別人提交的信息和作者,那么對(duì)你的腳本要求更高。
Git鉤子并不是用戶直接運(yùn)行的,所以要理解透如何獲取這些混亂卻重要的信息。事實(shí)上,一個(gè)Git鉤子腳本與其他任何腳本類似,像BASH、Python、C++或者其他腳本一樣的方式接受來(lái)自stdin的參數(shù)。不同的是,我們不會(huì)提供自己入?yún)?,所以使用它時(shí)要弄清楚你想要的是什么(參數(shù))。
編寫一個(gè)Git鉤子之前,可以進(jìn)入到你的項(xiàng)目目錄.git/hooks查看Git提供的范例。例如,下面是pre-push.sample文件的注釋部分:
1# $1 -- Name of the remote to which the push is being done
2# $2 -- URL to which the push is being done
3# If pushing without using a named remote those arguments will be equal.
4#
5# Information about commit is supplied as lines
6# to the standard input in this form:
7#
并非所有的范例寫的都那么清晰,文檔對(duì)于什么鉤子需要什么變量的說(shuō)明還有些不足(除非你要閱讀Git的源代碼),不過(guò)若有疑問(wèn),你可以通過(guò)trials of other users進(jìn)行更多地了解,或者編寫一個(gè)簡(jiǎn)單的腳本,輸出$1、$2、$3等。
分支檢測(cè)范例
我發(fā)現(xiàn)在實(shí)際的生產(chǎn)中對(duì)鉤子最常見的需求是針對(duì)受影響的分支觸發(fā)特定的事件。下面這個(gè)例子演示了如何解決這樣的任務(wù)。
首先,Git鉤子本身不是版本控制。也就是說(shuō),Git不會(huì)跟蹤它自己的鉤子,因?yàn)镚it鉤子是Git的組成部分而不是你的倉(cāng)庫(kù)的一部分。因此,Git鉤子在監(jiān)視提交和推送的同時(shí),可能對(duì)你的Git服務(wù)器上的遠(yuǎn)程倉(cāng)庫(kù)最有意義,而不是作為你的本地倉(cāng)庫(kù)的一部分。
我們來(lái)編寫一個(gè)基于post-receive運(yùn)行的鉤子(即,收到一個(gè)提交之后)。第一步是識(shí)別分支名字:
1#!/bin/tcsh
2foreach arg ( $< )
3set argv = ( $arg )
4set refname = $1
5end
for循環(huán)讀第一個(gè)參數(shù)($1),然后再次循環(huán)讀入第二個(gè)參數(shù)值($2),接著用第三個(gè)參數(shù)($3)再次循環(huán)。在Bash中有更好的方式:使用read命令,將這些值放入一個(gè)數(shù)組。但是,這里使用的是tcsh,并且變量順序是預(yù)先定義好的,這樣做要安全些。
當(dāng)有即將提交的refname時(shí),我們可以使用Git來(lái)獲取可讀性的分支名:
1set branch = `git rev-parse --symbolic --abbrev-ref $refname`
2echo $branch #DEBUG
這時(shí)我們可以將分支名與基于動(dòng)作名的關(guān)鍵字進(jìn)行比較:
01if ( "$branch" == "master" ) then
02echo "Branch detected: master"
03git \
04--work-tree=/path/to/where/you/want/to/copy/stuff/to \
05checkout -f $branch || echo "master fail"
06else if ( "$branch" == "dev" ) then
07echo "Branch detected: dev"
08Git \
09--work-tree=/path/to/where/you/want/to/copy/stuff/to \
10checkout -f $branch || echo "dev fail"
11else
12echo "Your push was successful."
13echo "Private branch detected. No action triggered."
14endif
授予腳本執(zhí)行權(quán)限:
1$ chmod +x ~/jupiter/.git/hooks/post-receive
當(dāng)用戶提交代碼到主服務(wù)器上的分支時(shí),這些代碼會(huì)被復(fù)制到生產(chǎn)環(huán)境的目錄中,當(dāng)代碼提交到開發(fā)環(huán)境上的分支時(shí),這些代碼會(huì)被復(fù)制到其它地方,而提交到其它任何分支上時(shí)不會(huì)觸發(fā)復(fù)制的操作。
檢測(cè)某人是否正在嘗試將代碼提交到本不應(yīng)該提交的分支上,或解析提交準(zhǔn)許日志,等等的這些操作都像預(yù)提交腳本一樣簡(jiǎn)單。
Git的鉤子(Hooks)能夠處理復(fù)雜的事情,同時(shí)它通過(guò)利用Git工作的抽象層讓人費(fèi)解,但它是一個(gè)強(qiáng)大的系統(tǒng),允許你設(shè)計(jì)所有Git基礎(chǔ)設(shè)施中的動(dòng)作。如果你只是想要熟悉這個(gè)過(guò)程,那你可以簡(jiǎn)單研究一下,如果你是一個(gè)嚴(yán)格的Git用戶或是全職的Git管理員,那你得要深研了!
在接下來(lái)的也就是此系列最后一篇文章,我們將學(xué)習(xí)怎么通過(guò)Git來(lái)管理非文本的大文件,如音頻文件、圖像文件。
看了“liunx ssh命令詳解”還想看:
2.linux命令ssh遠(yuǎn)程登錄命令簡(jiǎn)單實(shí)例
4.Linux命令SSH在本地執(zhí)行遠(yuǎn)程機(jī)器上的命令
5.ssh遠(yuǎn)程執(zhí)行命令方法和Shell腳本實(shí)例
-- URL to which the push is being done3# If pushing without using a named remote those arguments will be equal.
4#
5# Information about commit is supplied as lines
6# to the standard input in this form:
7#
并非所有的范例寫的都那么清晰,文檔對(duì)于什么鉤子需要什么變量的說(shuō)明還有些不足(除非你要閱讀Git的源代碼),不過(guò)若有疑問(wèn),你可以通過(guò)trials of other users進(jìn)行更多地了解,或者編寫一個(gè)簡(jiǎn)單的腳本,輸出 class="main">
liunx ssh命令詳解
liunx ssh命令詳解
目前為止,用戶對(duì)Git的焦點(diǎn)主要在Git的使用上。這篇文章中,我將論述如何管理Git以及自定Git架構(gòu)的設(shè)計(jì)。你可能會(huì)覺(jué)得這聽起來(lái)像“先進(jìn)的Git技術(shù)”或者“如果你是學(xué)霸讀這篇文章”的委婉說(shuō)法,但是事實(shí)上理解Git如何工作不需要任何的高深知識(shí)或者專業(yè)培訓(xùn),在一些情況下只需要了解一點(diǎn)Linux。分享Git服務(wù)
創(chuàng)建自己的Git服務(wù)共享非常簡(jiǎn)單, 在許多情況下值得去創(chuàng)建這樣一個(gè)Git服務(wù)。它不僅保證你隨時(shí)可以訪問(wèn)你的代碼,它的無(wú)限制數(shù)據(jù)存儲(chǔ)、持續(xù)集成跟部署同時(shí)為個(gè)人Git管理打開了一道Git延伸與拓展的大門。
假如你知道如何使用Git和SSH,那么你已經(jīng)知道如何創(chuàng)建一個(gè)Git服務(wù)器了。設(shè)計(jì)Git的方式,你創(chuàng)建或者克隆一個(gè)倉(cāng)庫(kù)時(shí),你已經(jīng)創(chuàng)建了一半服務(wù)器。使能SSH訪問(wèn)倉(cāng)庫(kù),并且任何訪問(wèn)你倉(cāng)庫(kù)的人都可以使用你的回購(gòu)協(xié)議作為一個(gè)新克隆的基礎(chǔ)。
但是,會(huì)有一個(gè)小特設(shè)。有些計(jì)劃你可以構(gòu)建關(guān)于同樣數(shù)量的精心設(shè)計(jì)的Git服務(wù)器,但是可以具有更好擴(kuò)展性。
首先是:識(shí)別你的用戶,包括閑雜與未來(lái)的。假如你是唯一用戶,那么無(wú)需任何改變,但是如果你邀請(qǐng)國(guó)外的貢獻(xiàn)者了,那么你應(yīng)該為開發(fā)者搭建一個(gè)貢獻(xiàn)共享系統(tǒng)平臺(tái)。
假定你有一個(gè)可用的服務(wù)器(如果不是,Git無(wú)法解決這個(gè)問(wèn)題,但是運(yùn)行在Raspberry Pi 3 的CentOS將會(huì)是一個(gè)良好開端),第一步是采用SSH鍵值授權(quán)登錄,它比密碼登錄更加強(qiáng)大,因?yàn)樗苊庖哂谛U力攻擊,并且可以避免用戶盡可能簡(jiǎn)單地刪除它們的鍵值。
在你啟用了SSH密鑰認(rèn)證之后,就創(chuàng)建一個(gè) gituser用戶。這是一個(gè)提供給所有通過(guò)了認(rèn)證的用戶的共享用戶賬號(hào):
1$ su -c 'adduser gituser'
然后切換到這個(gè)用戶,并使用合適的權(quán)限創(chuàng)建一個(gè) ~/.ssh 框架。這非常重要,因?yàn)槿绻麢?quán)限設(shè)置太過(guò)于隨意,你自己針對(duì)SSH的防護(hù)默認(rèn)就會(huì)失效。
1$ su - gituser
2$ mkdir .ssh && chmod 700 .ssh
3$ touch .ssh/authorized_keys
4$ chmod 600 .ssh/authorized_keys
authorized_keys 文件里面有所有你賦予其權(quán)限操作你的Git工程的開發(fā)者的SSH公共密鑰。你的開發(fā)者必須創(chuàng)建屬于他們自己的SSH密鑰并將其中的公共密鑰發(fā)送給你。要把這些公共密鑰復(fù)制到gituser的 authorized_keys 文件中去。例如,對(duì)于一個(gè)叫做Bob的開發(fā)者,可以運(yùn)行這些命令:
1$ cat ~/path/to/id_rsa.bob.pub >> \
2/home/gituser/.ssh/authorized_keys
當(dāng)開發(fā)者Bob持有能匹配他發(fā)送給你的公共密鑰的私有密鑰時(shí),他就能以gituser訪問(wèn)服務(wù)器。
不過(guò),你并不會(huì)真的想讓你的開發(fā)者訪問(wèn)到服務(wù)器,即使只是以gituser用戶來(lái)進(jìn)行訪問(wèn)。你想要的是讓他們只能訪問(wèn)到Git資源庫(kù)。因?yàn)檫@個(gè)原因,Git提供了一個(gè)受限的shell,恰如其分的將其稱為 git-shell、以root用戶運(yùn)行下面的這些命令可以將git-shell添加到你的系統(tǒng)中,并使其成為gituser用戶的默認(rèn)shell:
1# grep git-shell /etc/shells || su -c \
2"echo `which git-shell` >> /etc/shells"
3# su -c 'usermod -s git-shell gituser'
現(xiàn)在gituser只能使用SSH來(lái)向Git資源庫(kù)進(jìn)行推送和拉取操作,而不能訪問(wèn)到一個(gè)登陸shell。你應(yīng)該將你自己加入gituser對(duì)應(yīng)的用戶組,在我們的示例服務(wù)器中它還是gituser。
例如:
1# usermod -a -G gituser seth
剩下的唯一一個(gè)步驟就是創(chuàng)建一個(gè)Git資源庫(kù)。因?yàn)椴粫?huì)有人在服務(wù)器上跟它進(jìn)行直接交互(也就是說(shuō)你不會(huì)通過(guò)SSH連上服務(wù)器然后直接在資源庫(kù)中進(jìn)行操作), 這使其成為了一個(gè)基礎(chǔ)的資源庫(kù)。如果你想要把服務(wù)器上的資源庫(kù)用起來(lái),就要將其從它所在的地方克隆到自己的home目錄中去。
嚴(yán)格來(lái)說(shuō),你并不用使其成為一個(gè)基礎(chǔ)資源庫(kù),它還是可以作為一個(gè)普通的資源庫(kù)來(lái)操作的。不過(guò),一個(gè)基礎(chǔ)資源庫(kù)是沒(méi)有*工作樹(working tree)* (也就是說(shuō),不會(huì)有分支會(huì)處在”checkout“狀態(tài))。這很重要,因?yàn)檫h(yuǎn)程用戶不會(huì)被允許向一個(gè)活動(dòng)分支進(jìn)行推送 (你是不會(huì)想在一個(gè)”dev“分支工作時(shí)突然有人將變更推送到你的工作空間的?)。因?yàn)榛A(chǔ)資源庫(kù)不能有活動(dòng)分支,那就不會(huì)有問(wèn)題發(fā)生了。
你可以將資源庫(kù)放到任何你想要放置的地方, 只要你想賦予權(quán)限的用戶和組也能訪問(wèn)到它就行了。你不會(huì)想將目錄存儲(chǔ)到一個(gè)用戶的home目錄的,因?yàn)檫@里的權(quán)限相當(dāng)?shù)貒?yán)格, 而是要放在一個(gè)通用共享的位置,例如 /opt or /usr/local/share.
以root用戶創(chuàng)建一個(gè)基礎(chǔ)資源庫(kù):
1# git init --bare /opt/jupiter.git
2# chown -R gituser:gituser /opt/jupiter.git
3# chmod -R 770 /opt/jupiter.git
現(xiàn)在任何已gituser認(rèn)證的、或者是位于gituser分組的用戶都可以讀取和寫入jupiter.git資源庫(kù)。你可以在自己本機(jī)上試試看:
1$ git clone gituser@example.com:/opt/jupiter.git jupiter.clone
2Cloning into 'jupiter.clone'...
3Warning: you appear to have cloned an empty repository.
記?。洪_發(fā)有必須讓他們的公共SSH密鑰導(dǎo)入gituser用戶的 authorized_keys 文件, 或者是擁有服務(wù)器上面的賬戶(就像你一樣), 那樣的話他們就必須是gituser組的成員。
Git鉤子
運(yùn)行你自己的Git服務(wù)器帶來(lái)的一個(gè)好處是它提供了Git鉤子。Git托管服務(wù)有時(shí)也提供了一個(gè)類似鉤子的接口,但那并不是真正的可以訪問(wèn)文件系統(tǒng)的Git鉤子。一個(gè)Git鉤子是一個(gè)腳本,它在Git進(jìn)程中的某個(gè)時(shí)刻執(zhí)行。在一個(gè)倉(cāng)庫(kù)(repository)接受一個(gè)提交(commit)之前,或者收到一個(gè)提交之后,或者接收一個(gè)推送(push)之前,或者收到一個(gè)推送之后等時(shí)刻執(zhí)行一個(gè)鉤子。
這個(gè)系統(tǒng)很簡(jiǎn)單:任何可執(zhí)行的腳本都存放在.git/hooks目錄中,使用標(biāo)準(zhǔn)的命名方案,并且在某個(gè)指定的時(shí)刻執(zhí)行。腳本執(zhí)行的時(shí)間由名字來(lái)決定;pre-push腳本在推送之前執(zhí)行,post-receive腳本在收到一個(gè)提交之后執(zhí)行,諸如此類。它基本上屬于自文檔(self-documenting)。
可以使用任何語(yǔ)言編寫鉤子腳本;如果你能在你的系統(tǒng)上運(yùn)行某種語(yǔ)言的hello world腳本,那么你就可以使用那門語(yǔ)言來(lái)編寫Git鉤子腳本。默認(rèn)情況下,Git附帶了一些范例,但沒(méi)有啟用。
想要運(yùn)行一個(gè)腳本嗎?使用起來(lái)很簡(jiǎn)單。如果你還沒(méi)有Git倉(cāng)庫(kù)的話,首先創(chuàng)建一個(gè)。
1$ mkdir jupiter
2$ cd jupiter
3$ git init .
然后編寫一個(gè)"hello world" Git鉤子。由于在工作中我為了傳統(tǒng)支持而使用tcsh,所以我堅(jiān)持使用它作為我的腳本語(yǔ)言,但你可以自由地選用你喜愛(ài)的語(yǔ)言(Bash、Python、Ruby、Perl、Rust、Swift、Go):
1$ echo "#\!/bin/tcsh" > .git/hooks/post-commit
2$ echo "echo 'POST-COMMIT SCRIPT TRIGGERED'" > \
3~/jupiter/.git/hooks/post-commit
4$ chmod +x ~/jupiter/.git/hooks/post-commit
現(xiàn)在進(jìn)行測(cè)試:
1$ echo "hello world" > foo.txt
2$ git add foo.txt
3$ git commit -m 'first commit'
4! POST-COMMIT SCRIPT TRIGGERED
5[master (root-commit) c8678e0] first commit
61 file changed, 1 insertion(+)
7create mode 100644 foo.txt
這就是你的第一個(gè)可以正常運(yùn)行的Git鉤子。
著名的推送到web 鉤子
一個(gè)流行的Git鉤子用法是自動(dòng)推送改變部分到工作生產(chǎn)中的web服務(wù)器目錄。這是一個(gè)偉大構(gòu)建FTP的方式,保留開發(fā)環(huán)節(jié)的全版本控制,并且整合、自動(dòng)化發(fā)布內(nèi)容。
如果正確執(zhí)行,它將會(huì)工作運(yùn)行良好,在某一種程度來(lái)說(shuō),一直應(yīng)該做的是考慮如何網(wǎng)絡(luò)發(fā)布。它是不錯(cuò)的。我不知道最初是誰(shuí)想出這主意的,但是我第一次是從EMacs和來(lái)自IBM公司的Git-mentor、Bill Von Hagen那里聽到的。他的文章仍然是對(duì)這個(gè)過(guò)程起決定性作用的介紹:Git 改變分布式Web開發(fā)規(guī)則。
Git變量
每個(gè)Git鉤子獲取一組不同的Git動(dòng)作觸發(fā)它的相關(guān)變量。你可能會(huì)用到這些變量,也可能用不到。這取決于你所寫的作品。 如果你想要的是一個(gè)普通的郵件來(lái)通知你,有人推了東西。那么你不需要細(xì)節(jié),也不需要腳本,因?yàn)槟憧梢蕴子矛F(xiàn)有的樣板。如果你想在郵件里瀏覽別人提交的信息和作者,那么對(duì)你的腳本要求更高。
Git鉤子并不是用戶直接運(yùn)行的,所以要理解透如何獲取這些混亂卻重要的信息。事實(shí)上,一個(gè)Git鉤子腳本與其他任何腳本類似,像BASH、Python、C++或者其他腳本一樣的方式接受來(lái)自stdin的參數(shù)。不同的是,我們不會(huì)提供自己入?yún)?,所以使用它時(shí)要弄清楚你想要的是什么(參數(shù))。
編寫一個(gè)Git鉤子之前,可以進(jìn)入到你的項(xiàng)目目錄.git/hooks查看Git提供的范例。例如,下面是pre-push.sample文件的注釋部分:
1# $1 -- Name of the remote to which the push is being done
2# $2 -- URL to which the push is being done
3# If pushing without using a named remote those arguments will be equal.
4#
5# Information about commit is supplied as lines
6# to the standard input in this form:
7#
并非所有的范例寫的都那么清晰,文檔對(duì)于什么鉤子需要什么變量的說(shuō)明還有些不足(除非你要閱讀Git的源代碼),不過(guò)若有疑問(wèn),你可以通過(guò)trials of other users進(jìn)行更多地了解,或者編寫一個(gè)簡(jiǎn)單的腳本,輸出$1、$2、$3等。
分支檢測(cè)范例
我發(fā)現(xiàn)在實(shí)際的生產(chǎn)中對(duì)鉤子最常見的需求是針對(duì)受影響的分支觸發(fā)特定的事件。下面這個(gè)例子演示了如何解決這樣的任務(wù)。
首先,Git鉤子本身不是版本控制。也就是說(shuō),Git不會(huì)跟蹤它自己的鉤子,因?yàn)镚it鉤子是Git的組成部分而不是你的倉(cāng)庫(kù)的一部分。因此,Git鉤子在監(jiān)視提交和推送的同時(shí),可能對(duì)你的Git服務(wù)器上的遠(yuǎn)程倉(cāng)庫(kù)最有意義,而不是作為你的本地倉(cāng)庫(kù)的一部分。
我們來(lái)編寫一個(gè)基于post-receive運(yùn)行的鉤子(即,收到一個(gè)提交之后)。第一步是識(shí)別分支名字:
1#!/bin/tcsh
2foreach arg ( $< )
3set argv = ( $arg )
4set refname = $1
5end
for循環(huán)讀第一個(gè)參數(shù)($1),然后再次循環(huán)讀入第二個(gè)參數(shù)值($2),接著用第三個(gè)參數(shù)($3)再次循環(huán)。在Bash中有更好的方式:使用read命令,將這些值放入一個(gè)數(shù)組。但是,這里使用的是tcsh,并且變量順序是預(yù)先定義好的,這樣做要安全些。
當(dāng)有即將提交的refname時(shí),我們可以使用Git來(lái)獲取可讀性的分支名:
1set branch = `git rev-parse --symbolic --abbrev-ref $refname`
2echo $branch #DEBUG
這時(shí)我們可以將分支名與基于動(dòng)作名的關(guān)鍵字進(jìn)行比較:
01if ( "$branch" == "master" ) then
02echo "Branch detected: master"
03git \
04--work-tree=/path/to/where/you/want/to/copy/stuff/to \
05checkout -f $branch || echo "master fail"
06else if ( "$branch" == "dev" ) then
07echo "Branch detected: dev"
08Git \
09--work-tree=/path/to/where/you/want/to/copy/stuff/to \
10checkout -f $branch || echo "dev fail"
11else
12echo "Your push was successful."
13echo "Private branch detected. No action triggered."
14endif
授予腳本執(zhí)行權(quán)限:
1$ chmod +x ~/jupiter/.git/hooks/post-receive
當(dāng)用戶提交代碼到主服務(wù)器上的分支時(shí),這些代碼會(huì)被復(fù)制到生產(chǎn)環(huán)境的目錄中,當(dāng)代碼提交到開發(fā)環(huán)境上的分支時(shí),這些代碼會(huì)被復(fù)制到其它地方,而提交到其它任何分支上時(shí)不會(huì)觸發(fā)復(fù)制的操作。
檢測(cè)某人是否正在嘗試將代碼提交到本不應(yīng)該提交的分支上,或解析提交準(zhǔn)許日志,等等的這些操作都像預(yù)提交腳本一樣簡(jiǎn)單。
Git的鉤子(Hooks)能夠處理復(fù)雜的事情,同時(shí)它通過(guò)利用Git工作的抽象層讓人費(fèi)解,但它是一個(gè)強(qiáng)大的系統(tǒng),允許你設(shè)計(jì)所有Git基礎(chǔ)設(shè)施中的動(dòng)作。如果你只是想要熟悉這個(gè)過(guò)程,那你可以簡(jiǎn)單研究一下,如果你是一個(gè)嚴(yán)格的Git用戶或是全職的Git管理員,那你得要深研了!
在接下來(lái)的也就是此系列最后一篇文章,我們將學(xué)習(xí)怎么通過(guò)Git來(lái)管理非文本的大文件,如音頻文件、圖像文件。
看了“liunx ssh命令詳解”還想看:
2.linux命令ssh遠(yuǎn)程登錄命令簡(jiǎn)單實(shí)例
4.Linux命令SSH在本地執(zhí)行遠(yuǎn)程機(jī)器上的命令
5.ssh遠(yuǎn)程執(zhí)行命令方法和Shell腳本實(shí)例
、等。分支檢測(cè)范例
我發(fā)現(xiàn)在實(shí)際的生產(chǎn)中對(duì)鉤子最常見的需求是針對(duì)受影響的分支觸發(fā)特定的事件。下面這個(gè)例子演示了如何解決這樣的任務(wù)。
首先,Git鉤子本身不是版本控制。也就是說(shuō),Git不會(huì)跟蹤它自己的鉤子,因?yàn)镚it鉤子是Git的組成部分而不是你的倉(cāng)庫(kù)的一部分。因此,Git鉤子在監(jiān)視提交和推送的同時(shí),可能對(duì)你的Git服務(wù)器上的遠(yuǎn)程倉(cāng)庫(kù)最有意義,而不是作為你的本地倉(cāng)庫(kù)的一部分。
我們來(lái)編寫一個(gè)基于post-receive運(yùn)行的鉤子(即,收到一個(gè)提交之后)。第一步是識(shí)別分支名字:
1#!/bin/tcsh
2foreach arg ( $< )
3set argv = ( $arg )
4set refname = class="main">
liunx ssh命令詳解
liunx ssh命令詳解
liunx ssh命令詳解
目前為止,用戶對(duì)Git的焦點(diǎn)主要在Git的使用上。這篇文章中,我將論述如何管理Git以及自定Git架構(gòu)的設(shè)計(jì)。你可能會(huì)覺(jué)得這聽起來(lái)像“先進(jìn)的Git技術(shù)”或者“如果你是學(xué)霸讀這篇文章”的委婉說(shuō)法,但是事實(shí)上理解Git如何工作不需要任何的高深知識(shí)或者專業(yè)培訓(xùn),在一些情況下只需要了解一點(diǎn)Linux。分享Git服務(wù)
創(chuàng)建自己的Git服務(wù)共享非常簡(jiǎn)單, 在許多情況下值得去創(chuàng)建這樣一個(gè)Git服務(wù)。它不僅保證你隨時(shí)可以訪問(wèn)你的代碼,它的無(wú)限制數(shù)據(jù)存儲(chǔ)、持續(xù)集成跟部署同時(shí)為個(gè)人Git管理打開了一道Git延伸與拓展的大門。
假如你知道如何使用Git和SSH,那么你已經(jīng)知道如何創(chuàng)建一個(gè)Git服務(wù)器了。設(shè)計(jì)Git的方式,你創(chuàng)建或者克隆一個(gè)倉(cāng)庫(kù)時(shí),你已經(jīng)創(chuàng)建了一半服務(wù)器。使能SSH訪問(wèn)倉(cāng)庫(kù),并且任何訪問(wèn)你倉(cāng)庫(kù)的人都可以使用你的回購(gòu)協(xié)議作為一個(gè)新克隆的基礎(chǔ)。
但是,會(huì)有一個(gè)小特設(shè)。有些計(jì)劃你可以構(gòu)建關(guān)于同樣數(shù)量的精心設(shè)計(jì)的Git服務(wù)器,但是可以具有更好擴(kuò)展性。
首先是:識(shí)別你的用戶,包括閑雜與未來(lái)的。假如你是唯一用戶,那么無(wú)需任何改變,但是如果你邀請(qǐng)國(guó)外的貢獻(xiàn)者了,那么你應(yīng)該為開發(fā)者搭建一個(gè)貢獻(xiàn)共享系統(tǒng)平臺(tái)。
假定你有一個(gè)可用的服務(wù)器(如果不是,Git無(wú)法解決這個(gè)問(wèn)題,但是運(yùn)行在Raspberry Pi 3 的CentOS將會(huì)是一個(gè)良好開端),第一步是采用SSH鍵值授權(quán)登錄,它比密碼登錄更加強(qiáng)大,因?yàn)樗苊庖哂谛U力攻擊,并且可以避免用戶盡可能簡(jiǎn)單地刪除它們的鍵值。
在你啟用了SSH密鑰認(rèn)證之后,就創(chuàng)建一個(gè) gituser用戶。這是一個(gè)提供給所有通過(guò)了認(rèn)證的用戶的共享用戶賬號(hào):
1$ su -c 'adduser gituser'
然后切換到這個(gè)用戶,并使用合適的權(quán)限創(chuàng)建一個(gè) ~/.ssh 框架。這非常重要,因?yàn)槿绻麢?quán)限設(shè)置太過(guò)于隨意,你自己針對(duì)SSH的防護(hù)默認(rèn)就會(huì)失效。
1$ su - gituser
2$ mkdir .ssh && chmod 700 .ssh
3$ touch .ssh/authorized_keys
4$ chmod 600 .ssh/authorized_keys
authorized_keys 文件里面有所有你賦予其權(quán)限操作你的Git工程的開發(fā)者的SSH公共密鑰。你的開發(fā)者必須創(chuàng)建屬于他們自己的SSH密鑰并將其中的公共密鑰發(fā)送給你。要把這些公共密鑰復(fù)制到gituser的 authorized_keys 文件中去。例如,對(duì)于一個(gè)叫做Bob的開發(fā)者,可以運(yùn)行這些命令:
1$ cat ~/path/to/id_rsa.bob.pub >> \
2/home/gituser/.ssh/authorized_keys
當(dāng)開發(fā)者Bob持有能匹配他發(fā)送給你的公共密鑰的私有密鑰時(shí),他就能以gituser訪問(wèn)服務(wù)器。
不過(guò),你并不會(huì)真的想讓你的開發(fā)者訪問(wèn)到服務(wù)器,即使只是以gituser用戶來(lái)進(jìn)行訪問(wèn)。你想要的是讓他們只能訪問(wèn)到Git資源庫(kù)。因?yàn)檫@個(gè)原因,Git提供了一個(gè)受限的shell,恰如其分的將其稱為 git-shell、以root用戶運(yùn)行下面的這些命令可以將git-shell添加到你的系統(tǒng)中,并使其成為gituser用戶的默認(rèn)shell:
1# grep git-shell /etc/shells || su -c \
2"echo `which git-shell` >> /etc/shells"
3# su -c 'usermod -s git-shell gituser'
現(xiàn)在gituser只能使用SSH來(lái)向Git資源庫(kù)進(jìn)行推送和拉取操作,而不能訪問(wèn)到一個(gè)登陸shell。你應(yīng)該將你自己加入gituser對(duì)應(yīng)的用戶組,在我們的示例服務(wù)器中它還是gituser。
例如:
1# usermod -a -G gituser seth
剩下的唯一一個(gè)步驟就是創(chuàng)建一個(gè)Git資源庫(kù)。因?yàn)椴粫?huì)有人在服務(wù)器上跟它進(jìn)行直接交互(也就是說(shuō)你不會(huì)通過(guò)SSH連上服務(wù)器然后直接在資源庫(kù)中進(jìn)行操作), 這使其成為了一個(gè)基礎(chǔ)的資源庫(kù)。如果你想要把服務(wù)器上的資源庫(kù)用起來(lái),就要將其從它所在的地方克隆到自己的home目錄中去。
嚴(yán)格來(lái)說(shuō),你并不用使其成為一個(gè)基礎(chǔ)資源庫(kù),它還是可以作為一個(gè)普通的資源庫(kù)來(lái)操作的。不過(guò),一個(gè)基礎(chǔ)資源庫(kù)是沒(méi)有*工作樹(working tree)* (也就是說(shuō),不會(huì)有分支會(huì)處在”checkout“狀態(tài))。這很重要,因?yàn)檫h(yuǎn)程用戶不會(huì)被允許向一個(gè)活動(dòng)分支進(jìn)行推送 (你是不會(huì)想在一個(gè)”dev“分支工作時(shí)突然有人將變更推送到你的工作空間的?)。因?yàn)榛A(chǔ)資源庫(kù)不能有活動(dòng)分支,那就不會(huì)有問(wèn)題發(fā)生了。
你可以將資源庫(kù)放到任何你想要放置的地方, 只要你想賦予權(quán)限的用戶和組也能訪問(wèn)到它就行了。你不會(huì)想將目錄存儲(chǔ)到一個(gè)用戶的home目錄的,因?yàn)檫@里的權(quán)限相當(dāng)?shù)貒?yán)格, 而是要放在一個(gè)通用共享的位置,例如 /opt or /usr/local/share.
以root用戶創(chuàng)建一個(gè)基礎(chǔ)資源庫(kù):
1# git init --bare /opt/jupiter.git
2# chown -R gituser:gituser /opt/jupiter.git
3# chmod -R 770 /opt/jupiter.git
現(xiàn)在任何已gituser認(rèn)證的、或者是位于gituser分組的用戶都可以讀取和寫入jupiter.git資源庫(kù)。你可以在自己本機(jī)上試試看:
1$ git clone gituser@example.com:/opt/jupiter.git jupiter.clone
2Cloning into 'jupiter.clone'...
3Warning: you appear to have cloned an empty repository.
記?。洪_發(fā)有必須讓他們的公共SSH密鑰導(dǎo)入gituser用戶的 authorized_keys 文件, 或者是擁有服務(wù)器上面的賬戶(就像你一樣), 那樣的話他們就必須是gituser組的成員。
Git鉤子
運(yùn)行你自己的Git服務(wù)器帶來(lái)的一個(gè)好處是它提供了Git鉤子。Git托管服務(wù)有時(shí)也提供了一個(gè)類似鉤子的接口,但那并不是真正的可以訪問(wèn)文件系統(tǒng)的Git鉤子。一個(gè)Git鉤子是一個(gè)腳本,它在Git進(jìn)程中的某個(gè)時(shí)刻執(zhí)行。在一個(gè)倉(cāng)庫(kù)(repository)接受一個(gè)提交(commit)之前,或者收到一個(gè)提交之后,或者接收一個(gè)推送(push)之前,或者收到一個(gè)推送之后等時(shí)刻執(zhí)行一個(gè)鉤子。
這個(gè)系統(tǒng)很簡(jiǎn)單:任何可執(zhí)行的腳本都存放在.git/hooks目錄中,使用標(biāo)準(zhǔn)的命名方案,并且在某個(gè)指定的時(shí)刻執(zhí)行。腳本執(zhí)行的時(shí)間由名字來(lái)決定;pre-push腳本在推送之前執(zhí)行,post-receive腳本在收到一個(gè)提交之后執(zhí)行,諸如此類。它基本上屬于自文檔(self-documenting)。
可以使用任何語(yǔ)言編寫鉤子腳本;如果你能在你的系統(tǒng)上運(yùn)行某種語(yǔ)言的hello world腳本,那么你就可以使用那門語(yǔ)言來(lái)編寫Git鉤子腳本。默認(rèn)情況下,Git附帶了一些范例,但沒(méi)有啟用。
想要運(yùn)行一個(gè)腳本嗎?使用起來(lái)很簡(jiǎn)單。如果你還沒(méi)有Git倉(cāng)庫(kù)的話,首先創(chuàng)建一個(gè)。
1$ mkdir jupiter
2$ cd jupiter
3$ git init .
然后編寫一個(gè)"hello world" Git鉤子。由于在工作中我為了傳統(tǒng)支持而使用tcsh,所以我堅(jiān)持使用它作為我的腳本語(yǔ)言,但你可以自由地選用你喜愛(ài)的語(yǔ)言(Bash、Python、Ruby、Perl、Rust、Swift、Go):
1$ echo "#\!/bin/tcsh" > .git/hooks/post-commit
2$ echo "echo 'POST-COMMIT SCRIPT TRIGGERED'" > \
3~/jupiter/.git/hooks/post-commit
4$ chmod +x ~/jupiter/.git/hooks/post-commit
現(xiàn)在進(jìn)行測(cè)試:
1$ echo "hello world" > foo.txt
2$ git add foo.txt
3$ git commit -m 'first commit'
4! POST-COMMIT SCRIPT TRIGGERED
5[master (root-commit) c8678e0] first commit
61 file changed, 1 insertion(+)
7create mode 100644 foo.txt
這就是你的第一個(gè)可以正常運(yùn)行的Git鉤子。
著名的推送到web 鉤子
一個(gè)流行的Git鉤子用法是自動(dòng)推送改變部分到工作生產(chǎn)中的web服務(wù)器目錄。這是一個(gè)偉大構(gòu)建FTP的方式,保留開發(fā)環(huán)節(jié)的全版本控制,并且整合、自動(dòng)化發(fā)布內(nèi)容。
如果正確執(zhí)行,它將會(huì)工作運(yùn)行良好,在某一種程度來(lái)說(shuō),一直應(yīng)該做的是考慮如何網(wǎng)絡(luò)發(fā)布。它是不錯(cuò)的。我不知道最初是誰(shuí)想出這主意的,但是我第一次是從EMacs和來(lái)自IBM公司的Git-mentor、Bill Von Hagen那里聽到的。他的文章仍然是對(duì)這個(gè)過(guò)程起決定性作用的介紹:Git 改變分布式Web開發(fā)規(guī)則。
Git變量
每個(gè)Git鉤子獲取一組不同的Git動(dòng)作觸發(fā)它的相關(guān)變量。你可能會(huì)用到這些變量,也可能用不到。這取決于你所寫的作品。 如果你想要的是一個(gè)普通的郵件來(lái)通知你,有人推了東西。那么你不需要細(xì)節(jié),也不需要腳本,因?yàn)槟憧梢蕴子矛F(xiàn)有的樣板。如果你想在郵件里瀏覽別人提交的信息和作者,那么對(duì)你的腳本要求更高。
Git鉤子并不是用戶直接運(yùn)行的,所以要理解透如何獲取這些混亂卻重要的信息。事實(shí)上,一個(gè)Git鉤子腳本與其他任何腳本類似,像BASH、Python、C++或者其他腳本一樣的方式接受來(lái)自stdin的參數(shù)。不同的是,我們不會(huì)提供自己入?yún)ⅲ允褂盟鼤r(shí)要弄清楚你想要的是什么(參數(shù))。
編寫一個(gè)Git鉤子之前,可以進(jìn)入到你的項(xiàng)目目錄.git/hooks查看Git提供的范例。例如,下面是pre-push.sample文件的注釋部分:
1# $1 -- Name of the remote to which the push is being done
2# $2 -- URL to which the push is being done
3# If pushing without using a named remote those arguments will be equal.
4#
5# Information about commit is supplied as lines
6# to the standard input in this form:
7#
并非所有的范例寫的都那么清晰,文檔對(duì)于什么鉤子需要什么變量的說(shuō)明還有些不足(除非你要閱讀Git的源代碼),不過(guò)若有疑問(wèn),你可以通過(guò)trials of other users進(jìn)行更多地了解,或者編寫一個(gè)簡(jiǎn)單的腳本,輸出$1、$2、$3等。
分支檢測(cè)范例
我發(fā)現(xiàn)在實(shí)際的生產(chǎn)中對(duì)鉤子最常見的需求是針對(duì)受影響的分支觸發(fā)特定的事件。下面這個(gè)例子演示了如何解決這樣的任務(wù)。
首先,Git鉤子本身不是版本控制。也就是說(shuō),Git不會(huì)跟蹤它自己的鉤子,因?yàn)镚it鉤子是Git的組成部分而不是你的倉(cāng)庫(kù)的一部分。因此,Git鉤子在監(jiān)視提交和推送的同時(shí),可能對(duì)你的Git服務(wù)器上的遠(yuǎn)程倉(cāng)庫(kù)最有意義,而不是作為你的本地倉(cāng)庫(kù)的一部分。
我們來(lái)編寫一個(gè)基于post-receive運(yùn)行的鉤子(即,收到一個(gè)提交之后)。第一步是識(shí)別分支名字:
1#!/bin/tcsh
2foreach arg ( $< )
3set argv = ( $arg )
4set refname = $1
5end
for循環(huán)讀第一個(gè)參數(shù)($1),然后再次循環(huán)讀入第二個(gè)參數(shù)值($2),接著用第三個(gè)參數(shù)($3)再次循環(huán)。在Bash中有更好的方式:使用read命令,將這些值放入一個(gè)數(shù)組。但是,這里使用的是tcsh,并且變量順序是預(yù)先定義好的,這樣做要安全些。
當(dāng)有即將提交的refname時(shí),我們可以使用Git來(lái)獲取可讀性的分支名:
1set branch = `git rev-parse --symbolic --abbrev-ref $refname`
2echo $branch #DEBUG
這時(shí)我們可以將分支名與基于動(dòng)作名的關(guān)鍵字進(jìn)行比較:
01if ( "$branch" == "master" ) then
02echo "Branch detected: master"
03git \
04--work-tree=/path/to/where/you/want/to/copy/stuff/to \
05checkout -f $branch || echo "master fail"
06else if ( "$branch" == "dev" ) then
07echo "Branch detected: dev"
08Git \
09--work-tree=/path/to/where/you/want/to/copy/stuff/to \
10checkout -f $branch || echo "dev fail"
11else
12echo "Your push was successful."
13echo "Private branch detected. No action triggered."
14endif
授予腳本執(zhí)行權(quán)限:
1$ chmod +x ~/jupiter/.git/hooks/post-receive
當(dāng)用戶提交代碼到主服務(wù)器上的分支時(shí),這些代碼會(huì)被復(fù)制到生產(chǎn)環(huán)境的目錄中,當(dāng)代碼提交到開發(fā)環(huán)境上的分支時(shí),這些代碼會(huì)被復(fù)制到其它地方,而提交到其它任何分支上時(shí)不會(huì)觸發(fā)復(fù)制的操作。
檢測(cè)某人是否正在嘗試將代碼提交到本不應(yīng)該提交的分支上,或解析提交準(zhǔn)許日志,等等的這些操作都像預(yù)提交腳本一樣簡(jiǎn)單。
Git的鉤子(Hooks)能夠處理復(fù)雜的事情,同時(shí)它通過(guò)利用Git工作的抽象層讓人費(fèi)解,但它是一個(gè)強(qiáng)大的系統(tǒng),允許你設(shè)計(jì)所有Git基礎(chǔ)設(shè)施中的動(dòng)作。如果你只是想要熟悉這個(gè)過(guò)程,那你可以簡(jiǎn)單研究一下,如果你是一個(gè)嚴(yán)格的Git用戶或是全職的Git管理員,那你得要深研了!
在接下來(lái)的也就是此系列最后一篇文章,我們將學(xué)習(xí)怎么通過(guò)Git來(lái)管理非文本的大文件,如音頻文件、圖像文件。
看了“liunx ssh命令詳解”還想看:
2.linux命令ssh遠(yuǎn)程登錄命令簡(jiǎn)單實(shí)例
4.Linux命令SSH在本地執(zhí)行遠(yuǎn)程機(jī)器上的命令
5.ssh遠(yuǎn)程執(zhí)行命令方法和Shell腳本實(shí)例
),接著用第三個(gè)參數(shù)()再次循環(huán)。在Bash中有更好的方式:使用read命令,將這些值放入一個(gè)數(shù)組。但是,這里使用的是tcsh,并且變量順序是預(yù)先定義好的,這樣做要安全些。當(dāng)有即將提交的refname時(shí),我們可以使用Git來(lái)獲取可讀性的分支名:
1set branch = `git rev-parse --symbolic --abbrev-ref $refname`
2echo $branch #DEBUG
這時(shí)我們可以將分支名與基于動(dòng)作名的關(guān)鍵字進(jìn)行比較:
01if ( "$branch" == "master" ) then
02echo "Branch detected: master"
03git \
04--work-tree=/path/to/where/you/want/to/copy/stuff/to \
05checkout -f $branch || echo "master fail"
06else if ( "$branch" == "dev" ) then
07echo "Branch detected: dev"
08Git \
09--work-tree=/path/to/where/you/want/to/copy/stuff/to \
10checkout -f $branch || echo "dev fail"
11else
12echo "Your push was successful."
13echo "Private branch detected. No action triggered."
14endif
授予腳本執(zhí)行權(quán)限:
1$ chmod +x ~/jupiter/.git/hooks/post-receive
當(dāng)用戶提交代碼到主服務(wù)器上的分支時(shí),這些代碼會(huì)被復(fù)制到生產(chǎn)環(huán)境的目錄中,當(dāng)代碼提交到開發(fā)環(huán)境上的分支時(shí),這些代碼會(huì)被復(fù)制到其它地方,而提交到其它任何分支上時(shí)不會(huì)觸發(fā)復(fù)制的操作。
檢測(cè)某人是否正在嘗試將代碼提交到本不應(yīng)該提交的分支上,或解析提交準(zhǔn)許日志,等等的這些操作都像預(yù)提交腳本一樣簡(jiǎn)單。
Git的鉤子(Hooks)能夠處理復(fù)雜的事情,同時(shí)它通過(guò)利用Git工作的抽象層讓人費(fèi)解,但它是一個(gè)強(qiáng)大的系統(tǒng),允許你設(shè)計(jì)所有Git基礎(chǔ)設(shè)施中的動(dòng)作。如果你只是想要熟悉這個(gè)過(guò)程,那你可以簡(jiǎn)單研究一下,如果你是一個(gè)嚴(yán)格的Git用戶或是全職的Git管理員,那你得要深研了!
在接下來(lái)的也就是此系列最后一篇文章,我們將學(xué)習(xí)怎么通過(guò)Git來(lái)管理非文本的大文件,如音頻文件、圖像文件。
看了“liunx ssh命令詳解”還想看:
2.linux命令ssh遠(yuǎn)程登錄命令簡(jiǎn)單實(shí)例