Category Archives: IT: Linux

在已執行的 Docker 容器服務中獲得 Shell

獲得 Shell 後可以對容器內容做一些修改及監控,或是進一步了解作者在 Image 中包了哪些東西,Docker 容器服務若已經啟動,在不影響服務正常運行的情況下想要獲得 Shell 的話,最方便的應該就是容器開發模式中使用 nsenter 的方式。網路上眾多安裝 nsenter 方式以這個命令最簡便,不需額外套件與編譯直接安裝:

安裝方法

docker run -v /usr/local/bin:/target jpetazzo/nsenter

其 Github 的項目地址在:https://github.com/jpetazzo/nsenter 有興趣的朋友可以多多關注這個項目。

使用方式

先取得容器的 PID

PID=$(docker inspect --format {{.State.Pid}} <container_name_or_ID>)

根據 PID 獲得 Shell

$ sudo nsenter --target $PID --mount --uts --ipc --net --pid

簡化為 Shell Script <enter-cnt.sh>:

#!/bin/bash
echo "Looking PID for $1: "
PID=$(docker inspect --format {{.State.Pid}} $1)
echo $PID
sudo nsenter --target $PID --mount --uts --ipc --net --pid
ss_2016-02-28_21-08-56

網路上也有網友提供一個較複雜的 Shell 腳本 (轉自 http://www.hjue.me/post/docker-nsenter) 需要的朋友也可以參考:

#!/bin/sh
if [ -e $(dirname "$0")/nsenter ]; then
# with boot2docker, nsenter is not in the PATH but it is in the same folder
NSENTER=$(dirname "$0")/nsenter
else
NSENTER=nsenter
fi
if [ -z "$1" ]; then
echo "Usage: `basename "$0"` CONTAINER [COMMAND [ARG]...]"
echo ""
echo "Enters the Docker CONTAINER and executes the specified COMMAND."
echo "If COMMAND is not specified, runs an interactive shell in CONTAINER."
else
PID=$(docker inspect --format "{{.State.Pid}}" "$1")
if [ -z "$PID" ]; then
exit 1
fi
shift
OPTS="--target $PID --mount --uts --ipc --net --pid --"
if [ -z "$1" ]; then
# No command given.
# Use su to clear all host environment variables except for TERM,
# initialize the environment variables HOME, SHELL, USER, LOGNAME, PATH,
# and start a login shell.
"$NSENTER" $OPTS su - root
else
# Use env to clear all host environment variables.
"$NSENTER" $OPTS env --ignore-environment -- "$@"
fi
fi

Docker 自啟動容器

建立好一個容器後把它轉成服務,並設定在每次開機時自動啟動。在 CentOS 上我們使用的是 Systemd 而不是之前 Ubuntu 的 Upstart,Systemd 的約定中設定文件應放置在 /etc/systemd/system 或是 /usr/lib/systemd/system 下,由於某些系統預設安全性修改 /etc 下的檔案權限問題比較多,為了各系統間相容建議都放在 /usr/lib/systemd/system。

以下以 Dockerize 的 OpenVPN 容器設定為服務為例,容器確定已經可以正常運行之後,在上述目錄下建立一個 docker-openvpn.service 檔案:

sudo vi /usr/lib/systemd/system/docker-openvpn.service

內容為:

[Unit]
Description=OpenVPN Docker Service
Author=Coolfire
After=docker.service

[Service]
TimeoutSec=300
Restart=always
ExecStart=/usr/bin/docker start openvpn

[Install]
WantedBy=multi-user.target

然後測試是不是可以跑起來:

sudo systemctl start docker-openvpn
docker ps

如果已經跑起來了,那麼把它設定開機自啟動:

sudo systemctl enable docker-openvpn

如果需要確認可以重開機看看服務是否不需人工干預自動跑起來了。

CoreOS 可參考:
http://chuansong.me/n/1067253

dpkg 安裝軟體列表的備份方式

/* 刪除電腦中不用的小紙片 */
我們每個人都有過重裝系統的經歷,在安裝好系統之後,如何才能快速重裝原來那些自己所鍾愛的軟件?nixCraft 提供了一個有用的技巧。它的原理是在系統完好無損的時候,就做好已安裝軟件的備份工作。然後,在重裝系統後就可以利用先前備份的文檔來執行還原操作了。下面是相關的實施步驟(以 Debian 為例):

  1. 執行備份操作:
dpkg --get-selections > installed-software.log

這將當前系統中已安裝的軟件保存到 installed-software.log 中。

  1. 在還原時使用
dpkg --set-selections < installed-software.log

導入軟件列表,再利用 dselect 工具安裝軟件。
上述方法同樣適用於 Ubuntu。另外,原文也介紹了基於 RPM 包管理器的發行版如何執行的步驟,有興趣的可以直接去看。

sudo dpkg --set-selections /home/package.selections && apt-get dselect-upgrade

開機時自動啟動 Go Web 應用程式 – Upstart 設定方式

補上篇,Go Web 應用程式需要在 Command Line 下啟動,在 Production 環境中我們可以在 Ubuntu 中使用 Upstart 設定為開機時自動啟動,設定如下:

file: /etc/init/go-http.conf

# Upstart Configuration
description     "Golang Web App"
author          "xxxxx xxx"

start on (net-device-up
          and local-filesystems
          and runlevel [2345])
          
stop on runlevel [016]

respawn

exec /path/to/http

然後就可以使用這個指令來啟動:

$ sudo service go-http start
go-http start/running, process 12537

Upstart 在 Ubuntu like 系統上是預設安裝的應用程式,在其他的 Linux 下可能需要另外安裝。設定好了之後重新開機時就會像一般的 Daemon 一樣自動啟動應用程式。這個設定會在網路已經啟用的狀況下才啟動你指定的程式,對於 Upstart 有興趣深入了解的朋友可以參考這篇:http://upstart.ubuntu.com/cookbook/

2014/2/15 [補充] Debian 與 Ubuntu 都將支持使用 systemd 而不再用 Upstart, 因此稍晚這篇要改成 systemd 的設定方式。

在 Apache 上使用 VirtualHost 的方式執行 Golang 的 Web 站台

主要是參考網路上的這一篇:http://www.jeffreybolle.com/blog/run-google-go-web-apps-behind-apache

作者給出了一個簡單的 Go Web 程式:

package main

import(
    "http"
    "log"
    "os"
)

const resp = `<html>
    <head>
        <title>Simple Web App</title>
    </head>
    <body>
        <h1>Simple Web App</h1>
        <p>Hello World!</p>
    </body>
</html>`

func handler(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte(resp))
}

func main() {
    http.HandleFunc("/", handler)
    err := http.ListenAndServe(":8080", nil)

    if err != nil {
        log.Println(err)
        os.Exit(1)
    }
}

這個 Web 程式主要是監聽 8080 Port,用 go build 之後得到的執行檔可直接作為 Web Server 運行。然後在 Apache 上安裝幾個 Module 後重啟 Apache。

sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod rewrite
sudo service apache2 restart

接下來在 /etc/apache2/sites-available/ 目錄下建立 VirtualHost 的設定檔案 (gowebsite):

<VirtualHost *:80>
    ServerAdmin webmaster@example.com
    ServerName www.example.com
    ServerAlias example.com

    DocumentRoot /var/www
    <Directory />
        Options FollowSymLinks
        AllowOverride None
    </Directory>
    <Directory /var/www/>
        Options Indexes FollowSymLinks MultiViews
        AllowOverride None
        Order allow,deny
        allow from all

        RewriteEngine on
        RewriteRule ^(.*)$ http://localhost:8080/$1 [P,L]
    </Directory>
</VirtualHost>

接著在 Apache 啟動這個設定檔,將此 VirtualHost 設為啟動:

sudo a2ensite gowebsite
sudo service apache2 restart

整個過程就是在 VirtualHost 設定檔中設定此站台資料透過 Proxy Module 來由 localhost:8080 取得,當然這邊也可以同時在很多不同的 Port 中執行很多的 VirtualHost 站台。

Gitlab 整合 Active Directory 認證

Snip20140111_1

越來越多軟體開發人員使用 Git 作為版本控制器,可以像 Github 一樣開發協作的整合式版本控制平台的確迎合了許多企業的需求,因此有越來越多企業在內部架設 Gitlab 作為企業內的協作平台。企業內的應用整合 Active Directory 尤為重要,在人員離職的時帳號即被註銷,因此有較大的安全性。並且透過 LDAP 的機制,新進人員不用申請帳號即可設定使用 Guest 權限,讓每個企業員工都可以在 Gitlab 上報 Issue 並對 Issue 進行追蹤,加強了內部使用者與開發人員的溝通管道。

我的 Gitlab 版本選擇為 6.4-Stable,若是其他版本可能需要有其他額外或省略部分設定。
系統首選 Ubuntu 12.04 Server,這應該是大多數人的選擇。

Gitlab 的安裝可以參考官方文件:

https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/installation.md

另外有一份 Tsung 的中文版本可以參考:

http://blog.longwin.com.tw/2013/11/gitlab-ubuntu-linux-precise-2013/

整個安裝步驟看起來很複雜,其實在 Ubuntu 12.04 下照著說明一步步進行安裝,完全不會碰到什麼難解的特殊情況,我認為 Linux 新手也很容易能夠照說明安裝好一套 Gitlab。我第一次安裝因為網路慢的原因大概花了兩個多小時,後來安裝正式環境的時候大概因為比較熟練,一個多小時就完成安裝了。

針對安裝部分補充說明一下,「第一次啟動網頁要跑比較久」這個問題其實是可以透過 Precompile 解決的,網路上也有人說改 Timeout 值,但是有些比較慢的機器 Timeout 值改很大也沒什麼作用,這還是得從根本用 Precompile 解,直接用下列指令在第一次啟動後做 Precompile:

cd /home/git/gitlab; 
sudo bundle exec rake assets:precompile RAILS_ENV=production

好了,接下來回到正題。
整合 Active Directory 主要是參考網路上的這一篇:

https://raymii.org/s/tutorials/Gitlab_and_Active_Directory_LDAP_Authentication.html

一般來說如果你的 AD 環境不複雜直接照著做就可以成功了,但是我還是碰到了坑,主要是栽在這一段

bind_dn: &#039;CN=Gitlab LDAP,CN=Users,DC=Domain,DC=tld&#039;

原作者的 AD 環境可能比較簡單,建立的帳號直接在 CN=Users 下就可以找到,我設定的服務帳號卻一直都不成功,提示 “Invalid credentials“,網路上查詢到的都是要 Patch omniauth-ldap
的方法,不過那是在 Gitlab 5.4 的 Workaround 了,現在都過了大半年了以 Gitlab 的開發速度應該早就 Patch 掉了,因此不做考慮。接下來發現一個日本的網頁在說明 Gitlab AD 整合,其作者在 bind_dn 這段沒有用 CN=Users,而是使用了:

OU=DEPT,CN=Users,DC=Domain,DC=tld

這樣的語法,原來在 bind_dn 中需要指定完整的 LDAP 路徑 (Full LDAP path)

於是找到以前寫的程式查詢我所用的服務帳號到底是建在哪裡:

public string UserBelongOU (string s)
{
    Impersonator im = new Impersonator();
    im.Impersonate();
    try
    {
        DirectoryEntry entry = new DirectoryEntry("LDAP://DC=fetag,DC=net", Account, Password);
        DirectorySearcher mySearcher = new DirectorySearcher(entry);
        mySearcher.Filter = "(samAccountName=" + s + ")";
        SearchResultCollection result = mySearcher.FindAll();
        foreach(System.DirectoryServices.SearchResult resent in result)
        {
            string Return = "";
            Return = resEnt.Path;
            Return = "LDAP://" + Return.Substring(Return.IndexOf ("OU="));
            return Return;
        }
    } 
    catch {}
    im.Undo();
    return "";
}

結果是在

OU=NewTech,OU=IT,OU=Site,DC=fetag,DC=net

這麼一串下,然後修改 bind_dn:

bind_dn: &#039;CN=Gitlab Service,OU=NewTech,OU=IT,OU=Site,DC=fetag,DC=net&#039;

後重新啟動 Gitlab 就可以了。

加碼:如果有「LDAP 認證時使用 Filter」需求請參考底下這一篇:

http://blog.dimaj.net/content/howto-enable-ldap-filters-gitlab

原則上是需要 Patch omniauth-ldap,然後加上 filter 屬性,這樣可以在驗證時不是所有 Domain User 都能登入,而是在某個 Group 下的使用者才能夠登入使用 Gitlab。這一個做法只要是 LDAP 都可以,Active Directory 非必要。

[補充]
Gitlab 的備份與恢復可以參考:
https://github.com/gitlabhq/gitlabhq/blob/master/doc/raketasks/backup_restore.md

Keyword: Active Directory, Gitlab, Invalid credentials

Ubuntu 的企業形象 — 也許與你想的不同

SE-Skulls-1

Ubuntu 警告 電子前哨基金會的 Micah Lee 非法使用他們的商標,Micah Lee 在他的部落格上貼出了這一封信,原只是 Ubuntu Dash 中增加了搜尋功能可能導致隱私泄露,所以 Micah 建立了一個 Fix Ubuntu 的網站教導使用者如何手動移除這個搜索功能,沒想到 Ubuntu 會用這麼有損企業形象的方式來處理,真是打壞了我心中對 Ubuntu 的印象,這作法不僅違背了 Linux 的核心理念,也讓我這個資深使用者不太舒服,你們看完後怎麼想?


Update: [Mark Shuttleworth 道歉了]

對 Ubuntu 不穩定的 Unity 失望

安裝完了 11.4 之後 Unity 的界面整個亂閃亂跳,根本沒有辦法點選到想要的執行圖示,Thinkpad X60 雖然已經是幾年前的電腦了,可是照道理說它的硬體規格應該有廣大的市場。本以為是升級安裝的問題,所以改用全新安裝的方式,結果還是一樣,於是就必須得要放棄 (不穩定的) Unity 了,但是在 11.4 中 Unity 不只是預設的選項,而是必要選項,除非改用 Xbuntu 或是 Kbuntu… 於是乎,已經習慣了 Gnome 界面的我,安裝回 10.11 似乎是最方便的作法了,持續使用 10.11 中…

也許過陣子會換回 Debian, 選擇權還是在自己手中才算是自由呀。

Ubuntu PPTP VPN Install

Reference:
http://jkey.lu/install-pptp-on-ubuntu/
雖然沒那麼安全,但 PPTP 應該是最容易設定的 VPN 服務了,用來玩另一個地區提供的遊戲,應該是沒有什麼大問題的。想要安全性高一點的,當然是要選擇 IPSec + P2TP 了。

Ubuntu Desktop 更新至 10.10

昨天晚上在住的地方更新 Ubuntu 10.10 Desktop, 花了比預計還要長的時間,用慣了台北的網路,再用 China 的網路真是一整個不習慣,網路直接從 12M 降到了 1M, 平均下載也從 1.2MB/Sec 變成了 120KB/Sec, 再加上不穩定的網速,所以有時候會只有 60K/Sec 左右的速度,所以更新時跑 update-manager -d 下載的時間就佔用不少,中間我煮了晚餐,然後把晚餐給吃完了,下載還沒有完成,結果是連到土豆網去看了幾個短一點的片子,這當然又讓下載速度更慢了,下載更新套件花了一個多小時,最後安裝套件也花了一個多小時 (硬體也不夠力了),所以整體來說,透過網路直接更新,還不如下載 ISO 檔進行更新來得快。

今天再來嘗試連回台北,把 Server 也一併更新了吧。

[補充]
後來利用某個週末下午在星巴克喝咖啡泡時間的時候,連回台北進行了更新,一杯熱美式的時間完成了下載與安裝。

Copyright © 2017. Powered by WordPress & Romangie Theme.