2012/08/30

檔案比較與修正 diff and patch


檔案比較與修正 diff and patch

  • diff 比較檔案的異同
[lcc09@localhost ~]$ diff --help
用法:diff [選項]... FILES
比較兩個檔案的每一行。
  -i  --ignore-case           不分辨檔案內容中的大小寫。
  -E  --ignore-tab-expansion  忽略因將 tab 轉換為空格而造成的差異。
  -b  --ignore-space-change   忽略因空白字元數目不同而造成的差異。
  -w  --ignore-all-space      忽略所有空白字元。
  -B  --ignore-blank-lines    忽略任何因空行而造成的差異。
  -I RE  --ignore-matching-lines=RE  忽略任何符合指定的<正規表示式>的地方。
  --strip-trailing-cr      去除輸入資料每行末端的 carriage return 字元。
  -a  --text               所有檔案都以文字檔方式處理。
  -c  -C 行數  --context[=行數]  顯示指定<行數>(預設 3 行)copied 格式的上下文
  -u  -U 行數  --unified[=行數]  顯示指定<行數>(預設 3 行)unified 格式的上下文
  -q  --brief  只顯示檔案是否不同。
  -e  --ed     以 ed script 方式輸出。
  --normal     以正常的 diff 方式輸出。
  -n  --rcs    以 RCS diff 格式輸出。
  -y  --side-by-side         以兩列並排的方式顯示。
  -D NAME  --ifdef=NAME      輸出的資料以‘#ifdef NAME’方式標明差異。
  -l  --paginate           將輸出送至‘pr’指令來分頁。
  -t  --expand-tabs        將輸出中的 tab 換成空格。
  -T  --initial-tab        每行先加上 tab 字元,使 tab 字元可以對齊。
  -r  --recursive                連同所有副目錄一起比較。
  -N  --new-file                 不存在的檔案以空白檔案方式處理。
  --unidirectional-new-file      若第一個檔案不存在,以空白檔案處理。
  -s  --report-identical-files   當兩個檔案一樣時仍然顯示結果。
  -x PAT  --exclude=PAT          排除樣式為 PAT 的檔案。
  -X FILE  --exclude-from=FILE   排除所有在 FILE 中列出的樣式的檔案。
  -S FILE  --starting-file=FILE  當比較目錄時,由 FILE 開始比較。
...(略)...
  • patch 由 diff 所產生的patch file 來修正原始檔案的不同
  • 練習之前先建立兩個sample檔案
  • 檔名:diff_test.php 測試原始檔
[lcc09@localhost ~]$ vi diff_test.php
");
  echo ("
");
  echo ("\$    Dollar sign \\\$
");
  echo ("\\    Backslash \\\\ in double quotes
");
  echo ('\'    Single quote \\\'
');
  echo ('\\    Backslash \\\\ in single quotes
');
  echo ("\x41    ASCII code \\x41
");
  echo ("\141    ASCII code \\141
");
?>
  • 檔名:diff_test_err.php 測試修正檔
[lcc09@localhost ~]$ vi diff_test_err.php
");
  echo ("
");
  echo ("\$    Dollar sign \\\$
");
  echo ("\\    Backslash \\\\ in double quotes

");
  echo ('\'    Single quote \\\'
');
  echo ('\\    Backslash \\\\ in single quotes

');
  echo ("\x41    ASCII code \\x41
");
  echo ("\141    ASCII code \\141
");
?>
  • diff比較範例
  1. 這裏的-u是顯示出上下三行共通的程式碼以方便開發人員找出更新的地方。
[lcc09@localhost ~]$ diff -u diff_test_err.php diff_test.php
--- diff_test_err.php   2007-05-30 21:49:15.000000000 +0800
+++ diff_test.php       2007-05-30 21:48:19.000000000 +0800
@@ -4,9 +4,9 @@
   echo ("$cat *** " . '$dog' . "
");
   echo ("
");
   echo ("\$    Dollar sign \\\$
");
-  echo ("\\    Backslash \\\\ in double quotes

");
+  echo ("\\    Backslash \\\\ in double quotes
");
   echo ('\'    Single quote \\\'
');
-  echo ('\\    Backslash \\\\ in single quotes

');
+  echo ('\\    Backslash \\\\ in single quotes
');
   echo ("\x41    ASCII code \\x41
");
   echo ("\141    ASCII code \\141
");
?>
  • 把異動的部份存成檔案
[lcc09@localhost ~]$ diff -u diff_test_err.php diff_test.php > diff_test.php.patch
  • patch 自動依異動說明修正文字內容
[lcc09@localhost ~]$ patch --help
Usage: patch [OPTION]... [ORIGFILE [PATCHFILE]]
...(略)...
Backup and version control options:
  -b  --backup  Back up the original contents of each file.
  --backup-if-mismatch  Back up if the patch does not match exactly.
  --no-backup-if-mismatch  Back up mismatches only if otherwise requested.
...(略)...
  • 使用patch指令修正異動的地方,修正的方式參考diff_test.php.patch的檔案說明。這裡的-b是指在修正前要先備份備份附檔名為.orig。
[lcc09@localhost ~]$ patch -b diff_test_err.php diff_test.php.patch
patching file diff_test_err.php
[lcc09@localhost ~]$ cat diff_test_err.php
");
  echo ("
");
  echo ("\$    Dollar sign \\\$
");
  echo ("\\    Backslash \\\\ in double quotes
");
  echo ('\'    Single quote \\\'
');
  echo ('\\    Backslash \\\\ in single quotes
');
  echo ("\x41    ASCII code \\x41
");
  echo ("\141    ASCII code \\141
");
?>

2012/08/26

Linux iSCSI 的 target and initiator 的設定 (CentOS6)


iSCSI

iSCSI 又稱為IP-SAN,是一種基於網際網路及SCSI-3協議下的存儲技術,由IETF提出,並於2003年2月11日成為正式的標準。與傳統的SCSI技術比較起來,iSCSI技術有以下三個革命性的變化:
把原來只用於本機的SCSI協同透過TCP/IP網路傳送,使連接距離可作無限的地域延伸;
連接的伺服器數量無限(原來的SCSI-3的上限是15);
由於是伺服器架構,因此也可以實現在線擴容以至動態部署。
iSCSI Qualified Name (IQN)
Format: The iSCSI Qualified Name is documented in RFC 3720, with further examples of names in RFC 3721. Briefly, the fields are:
From the RFC:
                   Naming     String defined by
      Type  Date    Auth      "example.com" naming authority
     +--++-----+ +---------+ +-----------------------------+
     |  ||     | |         | |                             |    
  
     iqn.1992-01.com.example:storage:diskarrays-sn-a8675309
     iqn.1992-01.com.example
     iqn.1992-01.com.example:storage.tape1.sys1.xyz
通訊 port : TCP 3260
iSCSI target(伺服器)

CentOS6 iSCSI target and initiator 的設定
流程:
需要有各儲存裝置 (這裡以 LVM 切割出一塊裝置做使用)
安裝 target 服務
啟動服務
到 initiator 端,將 target 的分享掛載起來

需要有各儲存裝置 (以 lvm 的裝置示範)
[root@server1 ~]# lvcreate -l 3 -n iscsi10  vgsrv
  Logical volume "iscsi10" created

--- Logical volume ---
  LV Name                /dev/vgsrv/iscsi10
  VG Name                vgsrv
  LV UUID                VcQj9X-yhOD-wMDY-Sh2b-9Z8X-r0Cj-h08rB0
  LV Write Access        read/write
  LV Status              available
  # open                 0
  LV Size                96.00 MiB
  Current LE             3
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:3
安裝 target 服務
# 安裝 scsi-target-utils
[root@server1 ~]# yum install scsi-target-utils
修改 targets 服務設定 (詳細請見 man 5 targets.conf)
# 修改 targets 設定 (Linux SCSI Target Configuration File)
[root@server1 ~]# vim /etc/tgt/targets.conf
# 在檔案最後面加入這一段  

# target 名稱遵循 IQN 規範,通常用這樣的格式即可

# 設定儲存裝置來源
backing-store /dev/vgsrv/iscsi10
# 設定可存取的 initiator 位置
initiator-address 192.168.123.0/24
# 登入的學生帳號密碼
incominguser student PaSsWoRd


啟動 tgtd 服務(Linux SCSI Target Administration Utility)
# 重新啟動 tgtd 服務
[root@server1 ~]# /etc/init.d/tgtd restart

# tgtd 預設開機啟動
[root@server1 ~]# chkconfig tgtd on
show tgtadm 顯示設定檔狀況並驗證(詳細說明 man 8 tgtadm)
# show tgtadm 顯示 target 設定檔狀況並驗證
[root@server1 ~]# tgtadm --mode target --op show
Target 1: iqn.2012-05.world.server:target0
    System information:
        Driver: iscsi
        State: ready
    I_T nexus information:
    LUN information:
        LUN: 0
            Type: controller
            SCSI ID: IET     00010000
            SCSI SN: beaf10
            Size: 0 MB, Block size: 1
            Online: Yes
            Removable media: No
            Readonly: No
            Backing store type: null
            Backing store path: None
            Backing store flags:
        LUN: 1
            Type: disk
            SCSI ID: IET     00010001
            SCSI SN: beaf11
            Size: 101 MB, Block size: 512
            Online: Yes
            Removable media: No
            Readonly: No
            Backing store type: rdwr
            Backing store path: /dev/vgsrv/iscsi10 # 裝置代號
            Backing store flags:
    Account information:
        student  # 需要的登入帳號
    ACL information:
        192.168.123.0/24  # 可使用的主機存取控制
iSCSI Initiator(客戶端)

當有了 target 可以透過 initiator 探索 target 的資源,並且掛載使用。
到 initiator 端,將 target 的分享掛載起來,首要先探索伺服器提供 target 資源為何?
iscsiadm (open-iscsi administration utility) 詳細 man 8 iscsiadm
[root@desktop1 ~]# iscsiadm -m discovery -t st -p 192.168.123.194
Starting iscsid:                                           [  OK  ]
192.168.123.194:3260,1 iqn.2012-05.world.server:target0
加入預設登入密碼於設定檔內(因為剛剛在 target 有設定密碼,如果沒設定這段會在過程中發生錯誤)
# 因為 target 有設定密碼,所以需要設定這段.
[root@desktop1 ~]# vim /etc/iscsi/iscsid.conf
# To enable CHAP authentication set node.session.auth.authmethod
# to CHAP. The default is None.
node.session.auth.authmethod = CHAP

# To set a CHAP username and password for initiator
# authentication by the target(s), uncomment the following lines:
node.session.auth.username = student
node.session.auth.password = password
... 省略 ...
掛載 iscsi target ,這裡使用的是 -l 登入主機
[root@desktop1 ~]# iscsiadm -m node -T iqn.2012-05.world.server:target0 -p 192.168.123.194 -l
Logging in to [iface: default, target: iqn.2012-05.world.server:target0, portal: 192.168.123.194,3260]
Login to [iface: default, target: iqn.2012-05.world.server:target0, portal: 192.168.123.194,3260] successful.
找尋裝置代號需要透過 /var/log/message 的內容發現他掛載到那個裝置內,這裡是 /dev/sdb 這個裝置。
[root@desktop1 ~]# tail /var/log/messages
May  6 00:34:21 desktop1 kernel: scsi 4:0:0:0: Attached scsi generic sg2 type 12
May  6 00:34:21 desktop1 kernel: scsi 4:0:0:1: Direct-Access     IET      VIRTUAL-DISK     0001 PQ: 0 ANSI: 5
May  6 00:34:21 desktop1 kernel: sd 4:0:0:1: Attached scsi generic sg3 type 0
May  6 00:34:21 desktop1 kernel: sd 4:0:0:1: [sdb] 196608 512-byte logical blocks: (100 MB/96.0 MiB)
May  6 00:34:21 desktop1 kernel: sd 4:0:0:1: [sdb] Write Protect is off
May  6 00:34:21 desktop1 kernel: sd 4:0:0:1: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
May  6 00:34:21 desktop1 kernel: sdb: unknown partition table
May  6 00:34:21 desktop1 kernel: sd 4:0:0:1: [sdb] Attached SCSI disk
也可以透過 /dev/disk/by-path/ 目錄找尋載入的裝置名稱。
預設開機啟動掛載
[root@desktop1 ~]# chkconfig iscsi on
[root@desktop1 ~]# chkconfig iscsid on
掛到檔案系統使用,流程就和一般的硬碟使用方式一樣。需要格式化檔案系統、建立掛載點、掛載、寫入開機 /etc/fstab 等動作。
# 建立分割區
[root@desktop1 ~]# fdisk /dev/sdb
# 需要重開機後才可以發現這個分割區(partprobe 在 centos 6.3 還是不可以使用)

# 格式化為 ext4 檔案系統
[root@desktop1 ~]# mkfs -t ext4 /dev/sdb1
mke2fs 1.41.12 (17-May-2010)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
51200 inodes, 204592 blocks
10229 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=67371008
25 block groups
8192 blocks per group, 8192 fragments per group
2048 inodes per group
Superblock backups stored on blocks:
8193, 24577, 40961, 57345, 73729

Writing inode tables: done                            
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 22 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.

# 使用 UUIS 方式掛載
[root@desktop1 ~]# blkid /dev/sdb1
/dev/sdb1: UUID="66e276f3-fc47-472b-8037-acca7250c5e4" TYPE="ext4"

# 建立掛載點
[root@desktop1 ~]# mkdir /storage

# 寫入 /etc/fstab 確認開機啟動正常
[root@desktop1 ~]# vim /etc/fstab
... 略 ....
UUID=66e276f3-fc47-472b-8037-acca7250c5e4 /storage  ext4  _netdev  0 0

# 重新掛載所有檔案系統,並驗證。
[root@localhost ~]# mount -o remount -a
[root@localhost ~]# mount
... 略 ....
/dev/sdb1 on /storage type ext4 (rw,_netdev)
如果已經不需要使用,可以使用底下的方式移除
# -u 登出系統
[root@localhost ~]# iscsiadm -m node -T iqn.2012-05.world.server:target0 -p 192.168.123.194 -u
Logging out of session [sid: 2, target: iqn.2012-05.world.server:target0, portal: 192.168.123.194,3260]
Logout of [sid: 2, target: iqn.2012-05.world.server:target0, portal: 192.168.123.194,3260] successful.

# -o delete 刪除這個 node 在本機的記錄
[root@localhost ~]# iscsiadm -m node -T iqn.2012-05.world.server:target0 -p 192.168.123.194 -o delete

Linux 的 umask 及 suid , sgid 及sticky bit


預設權限

  • umask 可以透過 umask 指令設定.
  • 非受限的使用者 umask is 002
  1. 檔案權限為 664
  2. 目錄權限為 775
  • root 的 umask 是 022
  • 修改預設的權限
  1. 決定預設的存取權限 umask
  2. 目錄為 777(rwxrwxrwx) XOR umask值 = 建立的目錄權限
  3. 檔案為 666(rw-rw-rw-) XOR umask值 = 建立的檔案權限
  • 計算時要用二進位計算,檔案最後一碼為don't care(忽略),umask對於檔案的x權限無意義.目錄則無此問題.
  • XOR 計算真值表
ABXOR
000
011
101
110
  • 當 mask 為 022 時
  1. 目錄為
    1. 111 111 111 (777)
    2. 000 010 010 (022)
    3. =============================
    4. 111 101 101 (rwxr-xr-x) --> Don't use number and - to calculate
  2. 檔案為
    1. 11- 11- 11- (666)
    2. 000 010 010 (022)
    3. =======================
    4. 110 100 100 (rw-r--r--) --> Don't use number and - to calculate
[root@server1 ~]# umask 022
[root@server1 ~]# mkdir a
[root@server1 ~]# touch aa
[root@server1 ~]# ls -l
drwxr-xr-x 2 root root    4096 Aug 17 13:52 a
-rw-r--r-- 1 root root       0 Aug 17 13:52 aa
  • 當 mask 為 023 時
  1. 目錄為
    1. 111 111 111 (777)
    2. 000 010 011 (023)
    3. =========================
    4. 111 101 100 (???)
  2. 檔案為
    1. 11- 11- 11- (644)
    2. 000 010 011 (023)
    3. =========================
    4. 110 100 100 (???)
[root@server1 ~]# umask 023
[root@server1 ~]# mkdir b
[root@server1 ~]# touch bb
[root@server1 ~]# ls -l
drwxr-xr-- 2 root root    4096 Aug 17 13:52 b
-rw-r--r-- 1 root root       0 Aug 17 13:53 bb

Special Permissions for Executables

  • 設定特殊的檔案權限
  1. 3 種特殊的屬性
  2. s 與 t 的權限,是為了讓一般使用者在執行某些程式的時候, 能夠暫時的具有該程式擁有者的權限。
    1. t or T (1) Sticky bit
      1. 在具有 SBit 的目錄下,使用者若在該目錄下具有 w 及 x 的權限, 則當使用者在該目錄下建立檔案或目錄時,只有檔案擁有者與 root 才有權力刪除
      2. 如果將 A 目錄加上了 Sticky bit 的權限項目時, 則只能夠針對自己建立的檔案或目錄進行刪除/更名/移動等動作
    2. s or S (2) SGID (set GroupID?)
      1. 檔案:如果 SGID 是設定在 binary file 上面,則不論使用者是誰,在執行該程式的時候, 他的有效群組 (effective group) 將會變成該程式的群組所有人 (group id)。
      2. 目錄:如果 SGID 是設定在 A 目錄上面,則在該 A 目錄內所建立的檔案或目錄的 group,將會是此 A 目錄的group
    3. s or S (4) SUID (set UserID?) SUID
      1. 僅可用在『二進位制檔案(binary file)』
  3. 設定方法
    1. chmod 1xxx filename , chmod o+t filename
    2. chmod 2xxx filename , chmod g+s filename,
    3. chmod 4xxx filename , chmod u+s filename
# 目前狀態為1777
[root@localhost :~/tmp> la
drwxrwxrwt  2 root    root    72 2006-05-20 12:13 .
drwxr-xr-x 28 mtchang users 1760 2006-05-20 12:09 ..
-rwxrwxrwx  1 root    root     2 2006-05-20 12:13 a
[root@localhost :~/tmp> whoami
mtchang
[root@localhost :~/tmp> rm a
rm: 無法移除 ‘a’: 此項操作並不被允許
# 使用root切換回0777
mtchang@localhost:/home/mtchang # chmod 0777 tmp
# 使用mtchang使用者刪除a檔案
mtchang@localhost:~/tmp> rm a
mtchang@localhost:~/tmp> ll -la
drwxrwxrwx  2 root    root    48 2006-05-20 12:16 .
drwxr-xr-x 28 mtchang users 1760 2006-05-20 12:09 ..
# 確認刪除

Linux OpenSSH 及 Rsync


OpenSSH

OpenSSH: Secure Remote Shell

  • 具有加密功能,這是用來取代以前傳統明碼傳輸的遠端存取工具
  • 允許認證、加密存取遠端系統
  1. ssh [user@]hostname
  2. ssh [user@]hostname command
  • 要達成SSH的連線需要一個sshd server及一個ssh client
  • ssh client
  1. 在windows底下有這幾套軟體
  2. putty原始的putty中文可以顯示,但在輸入有點小問題。
  3. piettyputty的中文修改版,友善多了。
  4. winscp支援ssh ftp的程式,可以結合putty的帳號密碼
  5. 以上是windows上的免費工具
  • 在linux下可以直接使用ssh連線
[student@server1 ~]$ ssh --help
# 他的簡單參數說明
usage: ssh [-1246AaCfgkMNnqsTtVvXxY] [-b bind_address] [-c cipher_spec]
           [-D port] [-e escape_char] [-F configfile]
           [-i identity_file] [-L [bind_address:]port:host:hostport]
           [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]
           [-R [bind_address:]port:host:hostport] [-S ctl_path]
           [user@]hostname [command]

# 直接連線格式為:ssh 帳號@主機名稱
[student@server1 ~]$ ssh guest1@192.168.3.249
The authenticity of host '192.168.3.249 (192.168.3.249)' can't be established.
RSA key fingerprint is 90:8c:cd:57:e3:c8:27:50:92:39:e9:05:c8:3c:ae:84.
Are you sure you want to continue connecting (yes/no)? yes
# 第一次會因金鑰產生這問題,請回答yes加入此站台的key
Warning: Permanently added '192.168.3.249' (RSA) to the list of known hosts.
guest1@192.168.3.249's password: password(此範例密碼為password)
# 輸入你的密碼
[guest1@station249 ~]$ 
# 登入成功,你可以輸入指令了
  • SSH server
  • 通常都是用 opensshd 這個套件
[root@server1 ~]# rpm -qa | grep openssh
openssh-4.3p2-41.el5
openssh-clients-4.3p2-41.el5
openssh-server-4.3p2-41.el5
openssh-askpass-4.3p2-41.el5

[root@server1 ~]# /etc/init.d/sshd restart
# 重新啟動sshd
Shutting down SSH daemon                                              done
Starting SSH daemon                                                   done
# 正常這樣的話就可已使用ssh client登入主機了
  • 看你的 sshd 版本
[root@server1 ~]# telnet 192.168.3.249 22
Trying 192.168.3.249...
Connected to 192.168.3.249 (192.168.3.249).
Escape character is '^]'.
SSH-2.0-OpenSSH_4.3

Connection closed by foreign host. 
  • 連線到本機使用者 mtchang 並執行 whoami 指令
[root@cccm ~]# ssh mtchang@localhost 'whoami'
The authenticity of host 'localhost (127.0.0.1)' can't be established.
RSA key fingerprint is 15:bd:3a:e8:23:ce:92:88:cc:2e:49:07:5a:e6:7c:99.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'localhost' (RSA) to the list of known hosts.
mtchang@localhost's password:
mtchang

scp: 加密的檔案傳輸

  • Secure replacement for rcp
  • Layered on top of ssh
  1. scp source destination
  2. Remote files can be specified using:
  3. [user@]host:/path/to/file
  4. Use -r to enable recursion
  5. Use -p to preserve times and permissions
  6. Use -C to compress datastream
[root@server1 ~]# scp ks.cfg  guest1@192.168.3.249:/home/guest1/ks.cfg
guest1@192.168.3.249's password: 
ks.cfg                              100% 1582     1.5KB/s   00:00

[root@server1 ~]# ssh guest1@192.168.3.249  ls -la
guest1@192.168.3.249's password: 
總計 23
drwx------  4 guest1 users 1024  6月 11 05:12 .
drwxr-xr-x 39 root   root  1024  6月 11 04:49 ..
-rw-------  1 guest1 users   92  6月 11 05:08 .bash_history
-rw-r--r--  1 guest1 users   33  6月 11 04:48 .bash_logout
-rw-r--r--  1 guest1 users  176  6月 11 04:48 .bash_profile
-rw-r--r--  1 guest1 users  124  6月 11 04:48 .bashrc
-rw-r--r--  1 guest1 users  515  6月 11 04:48 .emacs
-rw-r--r--  1 guest1 users 1582  6月 11 05:12 ks.cfg
drwxr-xr-x  4 guest1 users 1024  6月 11 04:48 .mozilla
drwx------  2 guest1 users 1024  6月 11 05:01 .ssh
-rw-r--r--  1 guest1 users  658  6月 11 04:48 .zshrc

rsync: Efficient File Sync

  • 有效率的拷貝到遠端,目前大多數的mirror站台都是使用rsync來達到同步拷貝的功能
  • 使用安全的 ssh 連線來作傳輸
  • 速度比 scp 指令來的快,因為他只拷貝不同的檔案
  • 使用說明
Usage: rsync [OPTION]... SRC [SRC]... DEST
  or   rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST
  or   rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST
  or   rsync [OPTION]... SRC [SRC]... rsync://[USER@]HOST[:PORT]/DEST
  or   rsync [OPTION]... [USER@]HOST:SRC [DEST]
  or   rsync [OPTION]... [USER@]HOST::SRC [DEST]
  or   rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST]
The ':' usages connect via remote shell, while '::' & 'rsync://' usages connect
to an rsync daemon, and require SRC or DEST to start with a module name.
  • 簡單的本機同步範例
[root@localhost ~]# rsync /etc/sysconfig/ /root/backups/ -r
skipping non-regular file "selinux"
skipping non-regular file "network-scripts/ifdown"
skipping non-regular file "network-scripts/ifdown-isdn"
skipping non-regular file "network-scripts/ifup"
skipping non-regular file "network-scripts/ifup-isdn"
  • 遠端目錄同步範例(需要密碼)
[student@server1 ~]$ rsync guest1@192.168.3.249:/home/guest1/ \
/home/student/guest1/ -r
guest1@192.168.3.249's password: 
  • 遠端目錄同步範例(不需要密碼,因為已經使用 key-base 認證)
[student@server1 ~]$ rsync guest1@192.168.3.249:/home/guest1/ \
/home/student/guest1/ -r
[student@server1 ~]$ ls /home/student/guest1/ -l
總計 8
-rw-r--r-- 1 student student 1582  6月 10 21:37 ks.cfg

OpenSSH 以加密金鑰為認證方式

  • 不用密碼就可以認證登入ssh的主機
  • Uses two keys generated by ssh-keygen:
  • private key stays on your system
  1. Usually passphrase-protected (recommended)
  • public key is copied to destination with ssh-copy-id
  1. ssh-copy-id [user@]host
  2. 再比較舊的版本上面因為沒有ssh-copy-id這支程式,需要手動把公開金鑰(public key)放到遠端主機的 ~/.ssh/authorized_keys 檔案裡面。
  • 實作範例
  • 目的: 以CentOS server1主機上面的 student 帳號,登入到遠端主機 192.168.3.249 的 guestX(x是編號)
  • 以下產生本地端的 student 使用者的 id_dsa 私人金鑰及 id_dsa.pub 公開金鑰,請確認其權限為 600 on your provate key 及 644 on your public key。
[[student@server1 ~]$ ssh-keygen -t dsa
Generating public/private dsa key pair.

Enter file in which to save the key (/home/student/.ssh/id_dsa): 
Created directory '/home/student/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/student/.ssh/id_dsa.
Your public key has been saved in /home/student/.ssh/id_dsa.pub.
The key fingerprint is:
84:24:30:70:da:43:d3:b7:a1:2c:db:5d:e0:c3:42:d0 student@server1
  • 請連到遠端主機使用 ssh-keygen 產生遠端主機的私人金鑰及公開金鑰
  • 從本地端的 student 帳號複製 ~/.ssh/id_dsa.pub(公開金鑰)到遠端主機 192.168.3.249:/home/guest1/.ssh/authorized_keys 內
[student@server1 ~]$ scp ~/.ssh/id_dsa.pub guest1@192.168.3.249:/home/guest1/.ssh/authorized_keys
guest1@192.168.3.249's password: 
id_dsa.pub                                    100%  605     0.6KB/s   00:00  
  • 請注意,你的 /home/guest1/.ssh/ 目錄必須要存在才可以。
  • 在遠端的 192.168.3.249 的 guest1 帳號,確認authorized_keys 檔案已經被建立。
[guest1@station249 ~]$ ls /home/guest1/.ssh/ -l
總計 7
-rw-r--r-- 1 guest1 users  605  6月 11 05:01 authorized_keys
-rw------- 1 guest1 users 1675  6月 11 05:01 id_rsa
-rw-r--r-- 1 guest1 users  411  6月 11 05:01 id_rsa.pub
  • 可以觀察一下,這份公開金鑰的內容,如果有的二個使用者以上要加入,只需要把第二個使用的公開金鑰添加再後面即可。
[guest1@station249 ~]$ cat .ssh/authorized_keys 
ssh-dss AAAAB3NzaC1kc3MAAACBAJR1QgoEiGIJ+i901snf3pH15hX5OI2XRrwm
lun6eB
Kz75TMedjaxoITokv+iyuNZ7DG4hGZW+uAwucdrE+dzPd/eJyFJCabhyhMPGdbUj
/d1ZWIPy523JnrMdk9wxya+PG36o4YbzXr/kZSfhRK5i0KSNaRfBoQNB/jYcAw2s
UPAAAAFQDO06XMbkZvYTO/yA+ZixSX0A2xVwAAAIEAkOkpYnx5UZVpPnXAtwETQd
wTM5oZNFOaMRpcFQqfzGS
n0XoN6LfSBEIdeE3CHxfUHDAsij8n2Bm/f8yvgyUwEQo+BPMI6IrKOXGEQaT08So
1zKrvpAJnupsbtb3z8lN+jcI7c96G52tBkVPSkhoJkb/NpIVqQYjfLFcJborvz08
AAACAGDpauJRDPntn0VVcmxpefB7/pR0TSPLikEoY7MHQzmWA6kJP0U+PAf6XehL
tPg6eWdiFhNVqwIgf6O5kdIAczkFDNzlgm4nl3qPl3HiSDCKtcGXudhl4UhUkJr6
JFuj4/u5hglS92CB1XnUzPc5ZBe8u8+fyTyAHOrBcJvhslIM= student@server1

  • 再回到原本的主機 student 帳號,直接使用ssh client登入 guest1@192.168.3.249 主機
# 直接使用ssh client登入
[student@server1 ~]$ ssh guest1@192.168.3.249
Last login: Fri Jun 11 05:00:13 2010 from 192.168.3.250
[guest1@station249 ~]$ 
# 就這樣,不用密碼就登入了。

ssh-agent

  • ssh-agent 工具可以使用來儲存您的通行密碼(passphrase),以便不需在每次啟動 ssh 或 scp 連線時輸入通行密碼。
  • 假如您是使用 GNOME,openssh-askpass-gnome 工具可以用來當您登入 GNOME 時提示您輸入您的通行密碼,並儲存它直到您登出 GNOME。
  • 在該 GNOME 作業階段中所作的任何 ssh 或 scp 連線,都將不需要您輸入您的密碼或通行密碼。
  • 參考:
  1. http://freesf.tnc.edu.tw/docs/rh/rhl-cg-zh_TW-9/s1-openssh-client-config.html
  2. http://mah.everybody.org/docs/ssh

Linux -- find 指令用法


find

  • Find [directory...] [criteria...]
  1. 不同於 locate,Find 會實際去找檔案位置,但速度較慢,若沒有指定目錄,預設為cwd 目前工作目錄
  • 語法
[lcc09@localhost ~]$ find --help
用法:find [路徑...] [表達式]

預設路徑為目前的目錄,預設的表達式是 -print
表達式可以包括運算子、選項、測試和操作模式:
.....(略)
  • 基本上可以分成三個大項來看:
  1. [路徑...]搜尋路徑
  2. [表達式]搜尋的檔案條件,支援"Globbing"的語法。
  3. 動作action
    1. 命令執行(exec),屬"附加"性質,讓我們可以直接對 find 找到的檔案,運作指定的外部指令。
    2. 列印顯示(print),支援固定顯示。也可將顯示的資訊藉由選項直接存檔。
  4. 選項說明
    1. -daystart 起始時間以當日的 -amin, -atime, -cmin, -ctime, -mmin, 及 -mtime 為基準。
    2. -depth 處理目錄內容之後,再處理目錄本身。
    3. -follow 對符號連結的檔案或目錄不做檢查。隱含了 -noleaf 選項的作用。
    4. -help, --help 顯示程式用法資訊。
    5. -maxdepth levels 指定搜尋測試的最大目錄層數(levels)。對超過目錄層數的子目錄將不予以處理。
    6. -mindepth levels 指定搜尋測試的最小目錄層數(levels)。對 levels 內的目錄層數將不予以處理。
    7. -mount 只處理當前所在的檔案系統。不處理不同檔案系統(filesystems)的目錄。此選項在某些版本的 find 指令必須改用 -xdev 選項。
    8. -noleaf 捨棄檢查目錄是否有兩個硬連結(hard link)的優化處理。(程式預設的優化處理,在不必要時,反而會減緩搜尋測試的速度。如果使用者能理解自己檔案系統的硬連結狀況,適當地關閉預設的優化處理,將有助於速度的提昇)
    9. -version, --version 顯示程式本身的版本資訊。
    10. -xdev 只處理當前所在的檔案系統。對放置在不同檔案系統(filesystems)的目錄不做處理。
  • ex1
[lcc09@localhost ~]$ find / -name '*html' -type f 2>find.err >find.out
# 從「/」根目錄開始,找出檔名為*html 只列出type為f形式的資料
# -type 形式請自行參考man page說明
[lcc09@localhost ~]$ tail find.err 
find: /dev/VolGroup00: 拒絕不符權限的操作
find: /tmp/virtual-mtchang.o4WZCh: 拒絕不符權限的操作
find: /tmp/orbit-mtchang: 拒絕不符權限的操作
find: /tmp/virtual-mtchang.HdndkY: 拒絕不符權限的操作
find: /tmp/ssh-pPqrzi2340: 拒絕不符權限的操作
...(略)
[lcc09@localhost ~]$ tail find.out 
/usr/bin/post-grohtml
/usr/bin/pre-grohtml
/usr/bin/pod2html
/usr/lib/perl5/5.8.8/CGI/eg/index.html
/usr/lib/esc-1.0.0/chrome/content/esc/hiddenWindow.html
/usr/lib/esc-1.0.0/xulrunner/res/hiddenWindow.html
...(略)
  • ex2
[lcc09@localhost ~]$ find /usr/share/doc/ -name '*html' -type d
# 找出檔名為*html 只列出type為d形式的資料
/usr/share/doc/pam-0.99.6.2/html
/usr/share/doc/pyOpenSSL-0.6/html
/usr/share/doc/selinux-policy-2.4.6/html
/usr/share/doc/system-config-services-0.9.4/html
/usr/share/doc/libxslt-1.1.17/EXSLT/html
/usr/share/doc/libxslt-1.1.17/html
/usr/share/doc/sgml-common-0.6.3/html
  • ex3
[lcc09@localhost ~]$ mkdir ~/html
[lcc09@localhost ~]$ find /usr/share/doc/ -name 'man*.html' -type  f -exec cp {} ~/html \; -print
# copy set to ~/html 目錄
  • ex4
[lcc09@localhost ~]$ find /usr/share/doc/ -name 'man*.html' -type  f -exec grep samba-user {} \; -print
# 找出集合檔案中,帶有「samba-user」的行,並把他列印出來。
samba-user[%samba-password]
samba-user[%samba-password]
-U samba-user[%samba-password] /usr/share/doc/cups-1.2.4/help/man-cupsaddsmb.html
  • 練習:請解釋下面這一段命令的動作。
[lcc09@localhost ~]$ find / -name '*.mp3' -type f -exec rm -rf {} \; -print
  • find example:
find / -name foo.png (找檔名 foo.png)
find / -iname foo.png (不分大小寫,找檔名 foo.png)
find / -name "*.png" (找所有附檔名 .png 的檔案)
find / -user joe -group joe (找擁有者以及群組為 joe 的所有檔案)

 

Find and Logical Operations
邏輯上來講預設輸入的條件為 AND,其他也可以加入 -not,-o (or)
find -user joe -not -group joe (找使用者為joe,但 group 不為 joe)
find -user joe -o -user jane (找使用者為 joe 或者使用者為 jane)
find -not \(-user joe -o -user jane\) (找使用者不是 joe 也不是 jane)

 

Find and Permissions
find / -user joe -o -uid 500 (找使用者為 joe 或者 uid 為 500 的使用者)
find -perm 755 (找符合權限 755 的檔案)
find -perm +222 (找可寫入權限的檔案,不管任何人)
find -perm -222 (較嚴格,找全部人都有寫入權限的檔案)
find -perm -002 (other 有寫入權限的檔案)

 

find and Numberic Criteria
find -size 1024K (找檔案剛好等於 1MB)
find -size +1024K (找檔案超過 1MB)
find -size -1024K (找檔案小於 1MB)
find / -atime +5 (找檔案讀取日期超過 5 天)
find / -atime 5 (找檔案讀取日期剛好 5 天)
find / -atime -5 (找檔案讀取日期在 5 天以內)

-atime,when file was last read
-mtime,when file data last changed
-ctime,when file or metadata last changed 
find -ctime -10 (找10天以下有更動過檔案)
find -newer recent_file.txt (也可以跟某一個檔案比較有沒有比它更新)
find -not -newer recent_file.txt (也可以跟某一個檔案比較有沒有比它更舊)

 

Executing Commands with find
找到特定檔案之後,利用 -exec 或者 -ok 再進行進一步處理,其中 -ok 處理檔案時會逐一確認
find -size +1024K -ok gzip {} \; (代表檔案位置{},結束一定要用\;結束)
find -name "*.conf" -exec cp {} {}.orig \; (把所有 xxx.conf 檔案複製一份 xxx.conf.orig)
find /tmp -ctime +3 -user joe -ok rm {} \; (/tmp 中屬於 joe 的檔案超過三天沒更動,刪除,逐一確認)
find ~ -perm +o+w -exec chmod o-w {} \; (把 other 的寫入權限取消)

The Bash Shell (2)


The bash shell

Bash 變數

  • Variables are named values
  1. 常使用在儲存資料和命令的輸出
  • 設定變數的方式 VARIABLE=VALUE
  • 參考這個變數值 $VARIABLE
$ HI="Hello, and welcome to $(hostname)."
$ echo $HI
Hello, and welcome to stationX.
  • ex:
# 將 ls /etc 的值存入 files 變數
[mtchang@localhost ~]$ files=$(ls /etc/)
# 將變數內容取出
[mtchang@localhost ~]$ echo $files
a2ps.cfg a2ps-site.cfg acpi 
...(skip)...

Environment Variables

  • Variables are local to a single shell by default
  • Environment variables 無法傳遞到 child shells
  1. Set with export VARIABLE=VALUE
  2. Accessed by some programs for configuration
  • ex:
[mtchang@localhost ~]$ hi="hello, nice to meet you."
[mtchang@localhost ~]$ echo $hi
hello, nice to meet you.
  • set, env and echo 這三個指令都是用來顯示變數內容的
[mtchang@localhost ~]$ set | less
[mtchang@localhost ~]$ env | less
[mtchang@localhost ~]$ echo $HOME

一些常用的變數

  • Configuration variables
  • PS1: PS1的bash prompt提示符號變數:(man 1 bash是一本很棒的線上手冊)
  1. \h hostname
  2. \u user name
  3. \w 目前工作目錄
  4. \! history目前指令數量
  5. \$ 秀「$」這個文字符號
  • 節錄部份 man 1 bash 內容
mtchang@cccm:~<360>$ man 1 bash
PROMPTING
       When  executing  interactively,  bash  displays  the primary prompt PS1 when it is
       ready to read a command, and the secondary prompt PS2 when it needs more input  to
       complete  a command.  Bash allows these prompt strings to be customized by insert-
       ing a number of backslash-escaped special characters that are decoded as follows:
              \a     an ASCII bell character (07)
              \d     the date in "Weekday Month Date" format (e.g., "Tue May 26")
              \D{format}
                     the format is passed to strftime(3) and the result is inserted  into
                     the prompt string; an empty format results in a locale-specific time
                     representation.  The braces are required
              \e     an ASCII escape character (033)
              \h     the hostname up to the first ‘.’
              \H     the hostname
              \j     the number of jobs currently managed by the shell
              \l     the basename of the shell’s terminal device name
              \n     newline
              \r     carriage return
              \s     the name of the shell, the basename of $0 (the portion following the
                     final slash)
              \t     the current time in 24-hour HH:MM:SS format
              \T     the current time in 12-hour HH:MM:SS format
              \@     the current time in 12-hour am/pm format
              \A     the current time in 24-hour HH:MM format
              \u     the username of the current user
              \v     the version of bash (e.g., 2.00)
              \V     the release of bash, version + patch level (e.g., 2.00.0)
              \w     the current working directory, with $HOME abbreviated with a tilde
              \W     the  basename  of the current working directory, with $HOME abbrevi-
                     ated with a tilde
              \!     the history number of this command
              \#     the command number of this command
              \$     if the effective UID is 0, a #, otherwise a $
              \nnn   the character corresponding to the octal number nnn
              \\     a backslash
              \[     begin a sequence of non-printing characters, which could be used  to
                     embed a terminal control sequence into the prompt
              \]     end a sequence of non-printing characters
  • PATH: 可執行程式的路徑
  • EDITOR: 預設文字編輯器
  • HISTFILESIZE: Number of commands in bash history
  • 資訊變數
  1. HOME: User's home directory
  2. EUID: User's effective UID
  • PS1設定範例:
[lcc09@localhost ~]$ PS1="\u@\h:\w(\!)\$ "
lcc09@localhost:~(512)$ PS1="[\u@\h:\w]\$ "
[lcc09@localhost:~]$

Aliases

  • Aliases let you create shortcuts to commands
   $ alias dir='ls -laF'
  • Use alias by itself to see all set aliases
  • Use alias followed by an alias name to see alias value
     $ alias dir
     alias dir='ls -laF'
  • 綜合範例
[lcc09@localhost:~]$ alias
# 列出目前系統的別名
alias l.='ls -d .* --color=tty'
alias ll='ls -l --color=tty'
alias ls='ls --color=tty'
alias vi='vim'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
[lcc09@localhost:~]$ unalias vi
# 解除某個別名
[lcc09@localhost:~]$ alias
alias l.='ls -d .* --color=tty'
alias ll='ls -l --color=tty'
alias ls='ls --color=tty'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'

擴展 bash shell 命令列

  • 解釋為劃分為字包含 " ' | & ; ( ) < >
  • alias 能夠和其他指令混用
  • 解釋為 curly-brace statements ({})
# 擴展為 /etc/o* 及 /etc/c*
[root@cccm ~]# ls /etc/{o,c}*
  • 解釋為 tilde statements (~)
  • 解釋為 variables ($) 通常用 $ ${} $(()) $[] $() `
  • Expand file globs (*, ?, [abc], etc)
  • Prepare I/O redirections (<, >)
  • Run the command  !

Preventing Expansion(預防擴展)

  • Backslash ( \ ) 避免特殊字元被shell 解釋掉,具有脫逸某個字元的功能。
$ echo Your cost: \$5.00
Your cost: $5.00
  • Quoting(引號) prevents expansion
  1. Single quotes (') inhibit all expansion
  2. Double quotes (") inhibit all expansion, except:
  3. $ (dollar sign) - variable expansion
  4. ` (backquotes) - command substitution
  5. \ (backslash) - single character inhibition
  6.  ! (exclamation point) - history substitution
  • 請觀察 quoting 的差異
[root@cccm ~]# echo $HOME
/root
[root@cccm ~]# echo \$HOME
$HOME
[root@cccm ~]# echo '$HOME'
$HOME
[root@cccm ~]# echo "$HOME"
/root
[root@cccm ~]# echo `$HOME`
-bash: /root: is a directory

Login vs non-login shells

  • Startup is configured differently for login and non-login shells
  • Login shells are:
  1. Any shell created at login (includes X login)
  2. su -
  • Non-login shells are:
  1. su
  2. graphical terminals
  3. executed scripts
  4. any other bash instances
  • 請觀察其中的差異
[root@cccm ~]# su mtchang
[mtchang@cccm root]$ exit
exit
[root@cccm ~]# su - mtchang
[mtchang@cccm ~]$

Bash啟動工作指令稿

  • 再bash的啟動過程中,會依序載入這些啟動命令稿
  • 存儲在 /etc/profile (全域) and ~/.bash_profile (使用者)
  • 只有可以登入的 shell 才有作用
  • 通常用來
  1. 設定環境變數
  2. Running commands (eg. mail-checker script)
  • 存儲在 /etc/bashrc (全域) and ~/.bashrc (使用者)
  • Run for all shells
  • 通常用來
  1. Setting 本地端的變數
  2. Defining aliases(別名設定)
  • Bash 離開時的任務
  • 存儲在 ~/.bash_logout (user)
  • 在 login shell 離開時執行
  • 通常用來
  1. Creating automatic backups
  2. Cleaning out temporary files

Scripting

shell變數運算

(3.6) 變數的算數運算

在變數的算數運算方面 , 我們主要靠的是 expr 這個指令 . 各位
可以先在提示符號下試試 :

  % expr 30 + 20
  50
  % expr 30 - 20
  10
  % expr 30 \* 20     <-- * 是乘號 , 但要以反斜線去除特殊意義
  600
  % expr 30 / 20      <-- 只會取整數部份
  1

從上面我們可以看到 , expr 的確可以作整數的四則運算 . 但我們提
過 , 變數是沒有資料型別的 , 所以 expr 只能處理變數內容為可視
為整數的變數 . 如 :

  % var1=10
  % expr $var1 + 1        <-- 把 var1 加 1 

像下面就錯了 :

  % var1=10         
  % var2=20
  % expr var1 + var2      <-- var1 及 var2 不是內容 , $var1
  expr: non-numeric argument   $var2 才是

上面要改成 :

  % var1=10         
  % var2=20
  % expr $var1 + $var2  
  
下面是無意義的例子 :

  % var1=red
  % var2=green
  % expr $var1 + $var2    <-- expr 不能處理 red + green

那假如我們要把某一變數的內容加一再放回去呢 ?
如同 Pascal 中的 i:=i+1 , C 語言中的 i=i+1 那要如何作 ?   
很簡單 , 如下 :

  % i=`expr $i + 1`  

等號右邊的反單引號會先執行 , expr 把 i 加 1 然後再把得到
的結果指定給 i

命令列輸入的引數

  • Positional parameters are special variables that hold the command-line arguments to the script.
  • The positional parameters available are $1, $2, $3, etc. . These are normally assigned to more meaningful variable names to improve clarity.
  • $* holds all command-line arguments
  • $# holds the number of command-line arguments
  • 範例:
[lcc09@localhost:~]$ vi argu.sh  #vi建立一個script
#!/bin/bash
echo "The program name is $0"
printf "The first argument is %s and %s \n" $1 $2
echo "All argument are $*
[lcc09@localhost:~]$ chmod +x argu.sh  #賦予執行權限
[lcc09@localhost:~]$ ./argu.sh centos fedora linux is good #執行script並帶引數
The program name is ./argu.sh
The first argument is centos and fedora
All argument are centos fedora linux is good

Taking input with the read command

  • Use read to assign input values to one or more shell variables:
  1. -p designates prompt to display
  2. read reads from standard input and assigns one word to each variable
  3. Any leftover words are assigned to the last variable
  4. read -p "Enter a filename: " FILE
[lcc09@localhost:~]$ vi read.sh
#!/bin/bash
read -p "Enter name: " FIRST LAST
echo "first is $FIRST and last is $LAST"
[lcc09@localhost:~]$ ./read.sh
Enter name: mt chang
first is mt and last is chang

參考文件