Thursday, December 28, 2006

Use OpenSSL to Get Hash Values

echo "12345" | openssl sha1

echo "12345" | openssl md5

echo "12345" | openssl md2

Linux Hostname

看目前 hostname:
hostname

暫時改 hostname:
hostname new_name

更改 hostname:
vi /etc/sysconfig/network

Monday, December 25, 2006

Linux File Access Permissions

From
http://www.linuxfocus.org/English/January1999/article77.html


Abstract:

This article is divided into two parts:

* The first part (Basic file access permissions) is a very short introduction to the basic file permission concept under Unix.
* The second part (T-bit, SUID and SGID) covers more advanced features of Linux that go beyond the basic "read-write-execute" flags.



Basic file access permissions

Linux is a multiuser system where users can assign different access permission to their files. Every user has a user-Id, a unique number that identifies her/him. Users belong also to one or more groups. Groups can be used to restrict access to a number of people. A good feature to make team work with a number of people easier. To check your user-Id and see the group(s) to which you belong to just type the command id:

>id
uid=550(alice) gid=100(users) groups=100(users),6(disk)

Access permissions can be set per file for owner, group and others on the basis of read (r), write (w) and execute permissions (x). Your can use the command ls -l to see these permissions.

>ls -l /usr/bin/id
-rwxr-xr-x 1 root root 8632 May 9 1998 /usr/bin/id

The file /usr/bin/id is owned by user root and belongs to a group called root. The

-rwxr-xr-x

shows the file access permissions. This file is readable(r),writable(w) and executable(x) for the owner. For the group and all others it is readable(r) and executable(x).

You can imagine the the permissions as a bit vector with 3 bits each allocated to owner, group and others. Thus r-x corresponds to 101 as a bit pattern or 4+1=5 in decimal. The r-bit corresponds to decimal 4 the w-bit to decimal 2 and the x-bit to decimal 1.

sst
421
(discussed
later) rwx
421
user
(owner) rwx
421
group
rwx
421
others


The command chmod can be use to change these permission. For security reasons only root or the file owner may change the permissions. chmod takes either the decimal representation of the permissions or a symbolic representation. The symbolic representation is [ugoa][+-][rwx]. This is one of the letters u (user=file owner), g (group), o(others), a(all=u and g and o) followed by + or - to add or remove permissions and then the symbolic representation of the permissions in the form of r(read) w(write) x(execute). To make the file "file.txt" writable for all you type:

>chmod a+w file.txt
or
>chmod 666 file.txt
>ls -l file.txt
-rw-rw-rw- 1 alice users 79 Jan 1 16:14 file.txt

chmod 644 file.txt would set the permissions back to "normal" permissions with owner writable+readable and only readable for everyone else.

Changing into a directory (with the command cd) is equivalent to executing the directory. "Normal" permissions for a directory are therefore 755 and not 644:

>chmod 755 mydir
>ls -ld mydir
drwxr-xr-x 2 alice users 1024 Dec 31 22:32 mydir

The umask defines your default permissions. The default permissions are applied when new files (and directories, etc ...) are created. As argument it takes those bits in decimal representation that you do NOT want to have set.

umask 022 is e.g a good choice. With 022 everybody can read, your files and "cd" into directories but only you can modify things. To print the current umask settings just type umask without arguments.

Here is an example of how umask and chmod are used:

The umask is set to a good standard value
>umask
22

Take your editor and create a file called myscript:
>nedit myscript (or vi myscript ...)
Put the following code into it:

#!/bin/sh
#myscript
echo -n "hello "
whoami
echo "This file ( $0 ) has the following permissions:"
ls -l $0 | cut -f1 -d" "

Save the script.
Now it has 644 permissions:
>ls -l myscript
-rw-r--r-- 1 alice users 108 Jan 1 myscript
To run it you must make it executable:
>chmod 755 myscript
or
>chmod a+x myscript
Now run it:
>./myscript

Note that a script must be readable and executable in order to run where as a normal compiled binary needs only to be executable. This is because the script must be read be the interpreter (the shell). Running the script should produce:


hello alice
This file ( ./myscript ) has the following permissions:
-rwxr-xr-x


T-bit, SUID and SGID

After you have worked for a while with Linux you discover probably that there is much more to file permissions than just the "rwx" bits. When you look around in your file system you will see "s" and "t":

>ls -ld /usr/bin/crontab /usr/bin/passwd /usr/sbin/sendmail /tmp

drwxrwxrwt 5 root root 1024 Jan 1 17:21 /tmp
-rwsr-xr-x 1 root root 0328 May 6 1998 /usr/bin/crontab
-r-sr-xr-x 1 root bin 5613 Apr 27 1998 /usr/bin/passwd
-rwsr-sr-x 1 root mail 89524 Dec 3 22:18 /usr/sbin/sendmail

What is this "s" and "t" bit? The vector of permission bits is really 4 * 3 bits long. chmod 755 is only a shortcut for chmod 0755.

The t-bit

The t-bit (sometimes referred to as "sticky bit") is only useful in combination with directories. It is used with the /tmp directory as you can see above.

Normally (without the t-bit set on the directory) files can be deleted if the directory holding the files is writable for the person deleting files. Thus if you have a directory where anybody can deposit files then also anybody can delete the files of everybody else.

The t-bit changes this rule. With the t-bit set only the owner of the file or the owner of the directory can delete the files. The t-bit can be set with chmod a+tw or chmod 1777. Here is an example:

Alice creates a directory with t-bit set:
>mkdir mytmp
chmod 1777 mytmp

now Bob puts a file into it:
>ls -al
drwxrwxrwt 3 alice users 1024 Jan 1 20:30 ./
-rw-r--r-- 1 bob users 0 Jan 1 20:31 f.txt

This file can now be deleted by Alice (directory owner) and Bob (file owner) but it can not be deleted by Tux:

>whoami
tux
rm -f f.txt
rm: f.txt: Operation not permitted


S-bit set on the user

With Linux processes run under a user-ID. This gives them access to all resources (files etc...) that this user would have access to. There are 2 user IDs. The real user-ID and the effective user-ID. The effective user-ID is the one that determines the access to files. Save the following script under the name idinfo and make it executable (chmod 755 idinfo).


#!/bin/sh
#idinfo: Print user information
echo " effective user-ID:"
id -un
echo " real user-ID:"
id -unr
echo " group ID:"
id -gn

When you run the script you will see that the process that runs it gets your user-ID and your group-ID:

effective user-ID:
alice
real user-ID:
alice
group ID:
users

When Tux runs your idinfo program then he gets a similar output that shows the process now running under the ID of tux. The output of the program depends only on the user that runs it and not the one who owns the file.

For security reasons the s-bit works only when used on binaries (compiled code) and not on scripts (an exception are perl scripts). Therefore we create a C-program that will call our idinfo program:

/*suidtest.c*/
#include
#include
int main(){
/*secure SUID programs MUST
*not trust any user input or environment variable!! */

char *env[]={"PATH=/bin:/usr/bin",NULL};
char prog[]="/home/alice/idinfo";
if (access(prog,X_OK)){
fprintf(stderr,"ERROR: %s not executable\n",prog);
exit(1);
}
printf("running now %s ...\n",prog);
setreuid(geteuid(),geteuid());
execle(prog,(const char*)NULL,env);
perror("suidtest");

return(1);
}

Compile the program with "gcc -o suidtest -Wall suidtest.c" and set the s-bit on the owner:

>chmod 4755 suidtest
or
>chmod u+s suidtest

Run it! What happens? Nothing ? Run it from a different user!

The file suidtest is owned by alice and has the s-bit set where normally the x is for the owner of the file. This causes the file to be executed under the user-ID of the user that owns the file rather than the user that executes the file. If Tux runs the program then this looks as follows:

>ls -l suidtest
-rwsr-xr-x 1 alice users 4741 Jan 1 21:53 suidtest
>whoami
tux

running now /home/alice/idinfo ...
effective user-ID:
alice
real user-ID:
alice
group ID:
users

As you can see this is a very powerful feature especially if root owns the file with s-bit set. Any user can then do things that normally only root can do. A few words on security. When you write a SUID program then you must make sure that it can only be used for the purpose that you intended it to be used. Always set the path to a hard-coded value. Never rely on environment variables or functions that use environment variables. Never trust user input (config files, command line arguments....). Check user input byte for byte and compare it with values that you consider valid.

When a SUID program is owned by root then both the effective and the real user-ID can be set (with setreuid() function).

Set-UID programs are often used by "root" to give ordinary users access to things that normally only "root" can do. As root you can e.g modify the suidtest.c to allow any user to run the ppp-on/ppp-off scripts on your machine.

Note: It is possible to switch off Suid when mounting a file system. If the above does not work then check your /etc/fstab. It should look like this:
/dev/hda5 / ext2 defaults 1 1
If you find the option "nosuid" there then this Suid feature is switched off. For details have a look at the man-page of mount.

S-bit set on the group

Executable files the that have the s-bit set on the group run under the group-ID of the file owner. This is very similar to s-bit on user in the paragraph above.

When the s-bit is set on the group for a directory then the group is also set for every file that is created in that directory. Alice belong to 2 groups:

>id
uid=550(alice) gid=100(users) groups=100(users),6(disk)

Normally files are created for her with the group set to users. But if a directory is created with group set to disk and the s-bit set on the group then all files that alice creates have also the group ID disk:

>chmod 2775 .
>ls -ld .
drwxrwsr-x 3 tux disk 1024 Jan 1 23:02 .

If alice creates now a new file in this directory then the group of that file will be set to disk
>touch newfile
>ls -l newfile
-rw-r--r-- 1 alice disk 0 Jan 1 23:02 newfile

This is a good feature when you want to work with several people in a team and ensure that the group IDs of the files are set to the right group for the working directory of that team especially in an environment where users normally have a 027 umask that makes files un-accessible for people outside the group.

Saturday, December 23, 2006

LDAP with TLS

LDAP + SSL = port 636
LDAP + TLS = port 389 (no change)

Server:
(1) Create a cert for LDAP server
Note that the field of cn inside MUST match hostname

(2) Remove the DES3 password on private key
openssl rsa -in private.des3 -out slapd.pem

(3) add an empty line in the end of slapd.pem
echo >> slapd.pem

(4) append server's cert in the end of slapd.pem
cat newcert.pem >> slapd.pem

(5) cp slapd.pem /etc/openldap/cacerts/
chown root.ldap /etc/openldap/cacerts/slapd.pem
chmod 644 /etc/openldap/cacerts/slapd.pem

(6) cp cacert.pem /etc/openldap/cacerts/

(7) Modify slapd.conf
TLSCACertificateFile /etc/openldap/cacerts/cacert.pem
TLSCertificateFile /etc/openldap/cacerts/slapd.pem
TLSCertificateKeyFile /etc/openldap/cacerts/slapd.pem

(8) service ldap restart

(9) netstat -ntlp
Then, we can see both port 636 and 389 are being listen

Client:
(1) vi /etc/openldap/ldap.conf
TLS_REQCERT never

(2) search
TLS: ldapsearch -x -ZZ -b "dc=osa,dc=com" -h linux.kirka.idv.tw
SSL: ldapsearch -x -b "dc=osa,dc=com" -H ldaps://linux.kirika.idv.tw
No encrypt: ldapsearch -x -b "dc=osa,dc=com" -h linux.kirika.idv.tw

Linux:
Call authconfig, check "use TLS" in LDAP options
This will change /etc/ldap.conf
We can also change from TLS to SSL by changing
ssl start_tls
to
ssl on

Home Directory Solution for LDAP Linux Users

LDAP server: 10.0.1.11
User directory: 10.0.1.11:/rhome
LDAP user: kevin

Solution 1: use nfs to mount to another machine

Server:
(1) vi /etc/exports
/home 10.0.1.0/24 (rw)

(2) service nfs restart


Client:
(1) use root's account
mount 10.0.1.11:/rhome /home

(2) use ldap user kevin to login



Solution 2: use autofs with LDAP server

Server:
(1) vi /etc/exports
/home 10.0.1.0/24 (rw)

(2) service nfs restart

(3) Add LDAP Data
homeDirectory: /home/rhome/kevin
nisMapEntry: -w,hard,intr 10.0.1.11:/rhome/kevin
nisMapName: auto.misc
objectClass: nisObject

Client:
(1) vi /etc/auto.master
/home/rhome ldap:10.0.1.11:dc=osa,dc=com --timeout=60

This will automatically make a virtual directory which name
is the same as cn, namely, /home/rhome/kevin

(2) service autofs restart

(3) use kevin to login


ps. To add the nisObject with the /etc/passwd migration results,
we may need to change the schema /etc/openldap/schema/nis.schema:

objectclass ( 1.3.6.1.1.1.2.10 NAME 'nisObject'
DESC 'An entry in a NIS map'
SUP top AUXILIARY
MUST ( cn $ nisMapEntry $ nisMapName )
MAY description )

The 3rd line changed from "SUP top STRUCTURAL" to "SUP top AUXILIARY".

Friday, December 22, 2006

LDAP Replica

Master LDAP Server:
/etc/openldap/slapd.conf

access to attrs=userpassword
by self write
by * auth

access to *
by * read

suffix "dc=example,dc=com"
rootdn "cn=root,dc=example,dc=com"
rootpw 12345

# Replicas of this database
replogfile /var/lib/ldap/openldap-master-replog

replica host=slave.example.com:389
suffix="dc=example,dc=com"
binddn="cn=admin,dc=example,dc=com"
credentials=54321
bindmethod=simple


Slave LDAP Server:
suffix "dc=example,dc=com"
rootdn "cn=admin,dc=example,dc=com"
rootpw 54321

updatedn "cn=admin,dc=example,dc=com"
updateref ldap://master.example.com/

LDAP Partition

Parent LDAP server: ldap://tp.example.com:389/

dn: dc=example, dc=com
dc: example
objectclass: dcObject
objectclass: organizationalUnit
ou: example com

dn: ou=tp, dc=example, dc=com
objectclass: organizationalUnit
ou: tp

dn: ou=people, ou=tp, dc=example, dc=com
objectclass: organizationalUnit
ou: people

dn: ou=group, ou=tp, dc=example, dc=com
objectclass: organizationalUnit
ou: group

dn: cn=kevin, ou=group, ou=tp, dc=example, dc=com
....

dn: ou=ks, dc=example, dc=com
objectClass: referral
objectClass: extensibleobject
ou: ks
ref: ldap://ks.example.com/ou=ks,dc=example,dc=com


Child LDAP server: ldap://ks.example.com:389/

/etc/openldap/slapd.conf
referral ldap://tp.example.com:389/

dn: ou=ks, dc=example, dc=com
objectclass: organizationalUnit
ou: ks

dn: ou=people, ou=ks, dc=example, dc=com
objectclass: organizationalUnit
ou: people

dn: ou=group, ou=ks, dc=example, dc=com
objectclass: organizationalUnit
ou: group

dn: cn=david, ou=group, ou=ks, dc=example, dc=com

Query by ldapsearch:
Must add parameter -C to search for referrals

From parent (tp.example.com):
ldapsearch -x -C -b "dc=example,dc=com" "cn=david"

From child (ks.example.com):
ldapsearch -x -C -b "dc=example,dc=com" "cn=kevin"

Linux 開機時設定

vi /etc/inittab

# Default runlevel. The runlevels used by RHS are:
# 0 - halt (Do NOT set initdefault to this)
# 1 - Single user mode
# 2 - Multiuser, without NFS (The same as 3, if you do not have networking)
# 3 - Full multiuser mode
# 4 - unused
# 5 - X11
# 6 - reboot (Do NOT set initdefault to this)
#
id:3:initdefault:

選 5 預設開機為 X Window
選 3 預設開機為 Console Mode

提示符號含所在路徑

vi /etc/passwd
root:x:0:0:root:/root:/bin/tcsh

cd
vi .tcshrc
set prompt='[%n@%m %~]# '

Fedora 5 Console Font

Cannot open font file none:

vi /etc/sysconfig/i18n

LANG="ISO-8859-1.UTF-8"
SYSFONT="latarcyrheb-sun16"

LDAP vs. Linux Account

/usr/share/openldap/migration/

Change passwd to ldif:
migrate_passwd.pl

Change group to ldif:
migrate_group.pl

Modify migrate_passwd.pl:
if ($DEFAULT_MAIL_HOST) {
print $HANDLE "mailRoutingAddress: $user\@$DEFAULT_MAIL_HOST\n";
print $HANDLE "mailHost: $DEFAULT_MAIL_HOST\n";
print $HANDLE "mailLocalAddress: $user\@$DEFAULT_MAIL_DOMAIN\n";
print $HANDLE "objectClass: inetLocalMailRecipient\n";
}


Modify migrate_common.ph:
$DEFAULT_MAIL_DOMAIN = "kirika.idv.tw";
$DEFAULT_BASE = "ou=linux,dc=osa,dc=com"
$DEFAULT_MAIL_HOST = "linux.kirika.idv.tw"
$EXTENDED SCHEMA = 1;

LDAP - osa_top.ldif

dn: dc=osa, dc=com
dc: osa
objectClass: dcObject
objectClass: organizationalUnit
ou: osa com

dn: ou=linux, dc=osa, dc=com
objectclass: organizationalUnit
ou: linux

dn: ou=people, ou=linux, dc=osa, dc=com
objectclass: organizationalUnit
ou: people

dn: ou=group, ou=linux, dc=osa, dc=com
objectclass: organizationalUnit
ou: group

Wednesday, December 20, 2006

LDAP - top.ldif

dn: dc=example, dc=com
objectclass: top

dn: ou=tp, dc=example, dc=com
objectclass: organizationalUnit
ou: tp

dn: ou=ks, dc=example, dc=com
objectclass: organizationalUnit
ou: ks

dn: ou=people, ou=tp, dc=example, dc=com
objectclass: organizationalUnit
ou: people

dn: ou=group, ou=tp, dc=example, dc=com
objectclass: organizationalUnit
ou: group

dn: ou=people, ou=ks, dc=example, dc=com
objectclass: organizationalUnit
ou: people

dn: ou=group, ou=ks, dc=example, dc=com
objectclass: organizationalUnit
ou: group

LDAP vs. Outlook Express - kevin.ldif

dn: uid=kevin,ou=People,ou=tp,dc=example,dc=com
uid: kevin
mailRoutingAddress: kevin@tp.example.com
mailHost: tp.example.com
mailLocalAddress: kevin@example.com
objectClass: inetLocalMailRecipient
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: top
objectClass: kerberosSecurityObject
objectClass: shadowAccount
objectClass: country
objectClass: officePerson
userPassword: 12345
shadowLastChange: 13495
shadowMax: 99999
shadowWarning: 7
krbName: kevin@EXAMPLE.COM
loginShell: /bin/bash
uidNumber: 500
gidNumber: 500
homeDirectory: /home/kevin
sn: 王
givenName: 大明
mail: jacky_chen@example.com
cn: kevin
st: 台北
c: 台灣
organizationName: Example
organizationalUnitName: 業務部
URL: http://edu.uuu.com.tw
facsimileTelephoneNumber: 886-2-1234-5678
pager: 886-2-8765-4321
title: 講師
telephoneNumber: 886-2-1234-4321
l: 中正
postalAddress: 復興北路99號
postalCode: 105
physicalDeliveryOfficeName: 19F
IPPhone: 1.2.3.4
comment: 員工
conferenceInformation: 1.2.3.4

LDAP vs. Outlook Express - userdefine.schema

attributetype (1.3.6.1.4.1.4203.666.100.123
NAME 'IPPhone'
SUP telephoneNumber )

attributetype (1.3.6.1.4.1.4203.666.100.124
NAME 'URL'
SUP name )

attributetype (1.3.6.1.4.1.4203.666.100.125
NAME 'comment'
SUP name )

attributetype (1.3.6.1.4.1.4203.666.100.126
NAME 'conferenceInformation'
SUP name )

objectclass (1.3.6.1.4.1.4203.666.100.1
NAME 'officePerson'
SUP inetOrgPerson
DESC 'Office employee or computer user'
MAY ( IPPhone $
URL $
comment $
conferenceInformation ) )

RedHat RPM

query:
rpm -qa | grep xxx

install:
rpm -ivh xxx.rpm

upgrade:
rpm -Uvh xxx.rpm

build rpm src:
rpmbuild --rebuild filename.src.rpm

rpm -Uvh alien-6.51-1.src.rpm
rpm -bb /usr/src/redhat/SPECS/alien-6.51-1.spec
rpm -Uvh /usr/src/redhat/RPMS/i386/alien-5.51-1.rpm

OpenLDAP 指令

ldapsearch -x -b "dc=osa,dc=com" "(cn=Janny)"

ldapadd -x -W -D "cn=root,dc=osa,dc=com" -f my.ldif

ldapmodify -x -W -D "cn=root,dc=osa,dc=com" -f my.ldif

ldapdelete -x -W -D "cn=root,dc=osa,dc=com" "cn=janny,ou=linux,dc=osa,dc=com"

ps. To delete the whole database
service ldap stop
rm -f /var/lib/ldap/*

ps2. We can set some default values for these commands
vi /etc/openldap/ldap.conf

BASE dc=osa,dc=com
#URI ldap://ldap.example.com ldap://ldap-master.example.com:666
URI ldap://linux.kirika.idv.tw
HOST linux.kirika.idv.tw

#SIZELIMIT 12
#TIMELIMIT 15
#DEREF never
TLS_CACERTDIR /etc/openldap/cacerts
TLS_REQCERT never

Then, we don't need to give -b and -h in the commands.

Tuesday, December 19, 2006

Certification

Fidora 4.0 路徑:
/etc/pki/tls/misc/CA

RedHat Enterprise 3.0/4.0 路徑:
/usr/share/ssl/misc

產生 Root CA:
./CA -newca

看 Cert 編碼後內容:
cd ../../CA
openssl x509 -in cacert.pem -noout -text

產生 Cert Request:
./CA -newreq

看 Cert REQ 編碼後內容:
openssl req -in newreq.pem -noout -text

分出 private key:
head -18 newreq.pem > private.des3

簽發 Cert:
./CA -sign

更改 Root CA 的有效期限:
vi CA
DAYS="-days 3650"

更改簽發出來的 Cert 的有效期限:
vi /etc/pki/tls/openssl.cnf
default_days = 730 # how long to certify for
default_crl_days= 30 # how long before next CRL
default_md = sha1 # which md to use.
preserve = no # keep passed DN ordering

拿掉 private key 上的 DES3:
openssl rsa -in private.des3 -out private.key

將 Cert 匯入 LDAP 必須先轉成 .der 格式
openssl x509 -in newcert.pem -outform der -out newcert.der

LDIF 檔內 attribute
userCertificate;binary:<file:///path/newcert.der

將個人 Cert 匯入 Outlook Express 必須先轉成 pkcs12 格式
此種格式同時含有 Cert 及 private key
openssl pkcs12 -export -in newcert.pem -out newcert.p12 -inkey private.key

進階 vi 教學

.vi 的操作模式
==============
vi 提供兩種操作模式:輸入模式(insert mode)和指令模式(command mode)
。當使用者進入 vi 後,即處在指令模式下,此刻鍵入之任何字元皆被視為
指令。在此模式下可進行刪除、修改等動作。若要輸入資料,則需進入輸入
模式。

.輸入模式
=========
如何進入輸入模式
a (append) 由游標之後加入資料。
A 由該行之末加入資料。
i (insert) 由游標之前加入資料。
I 由該行之首加入資料。
o (open) 新增一行於該行之下供輸入資料之用。
O 新增一行於該行之上供輸入資料之用。

如何離開輸入模式
《ESC》 結束輸入模式。

.指令模式
=========
游標之移動
h 向左移一個字元。
j 向上移一個字元。
k 向下移一個字元。
l 向右移一個字元。
0 移至該行之首
$ 移至該行之末。
^ 移至該行的第一個字元處。
H 移至視窗的第一列。
M 移至視窗的中間那列。
L 移至視窗的最後一列。
G 移至該檔案的最後一列。
+ 移至下一列的第一個字元處。
- 移至上一列的第一個字元處。
( 移至該句之首。 (註一)
) 移至該句之末。
{ 移至該段落之首。 (註二)
} 移至該段落之末。
nG 移至該檔案的第 n 列。
n+ 移至游標所在位置之後的第 n 列。
n- 移至游標所在位置之前的第 n 列。
[Ctrl][g] 會顯示該行之行號、檔案名稱、檔案中最末行之行號、游標
所在行號佔總行號之百分比。

註一:句子(sentence)在vi中是指以『!』、『.』或『?』結束的一串字。
註二:段落(paragraph)在vi中是指以空白行隔開的文字。

.視窗的移動
===========
[Ctrl][f] 視窗往下捲一頁。
[Ctrl][b] 視窗往上捲一頁。
[Ctrl][d] 視窗往下捲半頁。
[Ctrl][u] 視窗往上捲半頁。
[Ctrl][e] 視窗往下捲一行。
[Ctrl][y] 視窗往上捲一行。

.刪除、複製及修改指令介紹 (此單元較少使用)
=========================
d(delete)、c(change)和y(yank)這一類的指令在 vi 中的指令格式為:
Operator + Scope = command
(運算子) (範圍)
運算子:
d 刪除指令。刪除資料,但會將刪除資料複製到記憶體緩衝區。
y 將資料(字組、行列、句子或段落)複製到緩衝區。
p 放置(put)指令,與 d 和 y 配和使用。可將最後delete或yank的資
料放置於游標所在位置之行列下。
c 修改(change)指令,類似delete與insert的組和。刪除一個字組、句
子等之資料,並插入新鍵資料。

範圍:
e 由游標所在位置至該字串的最後一個字元。
w 由游標所在位置至下一個字串的第一個字元。
b 由游標所在位置至前一個字串的第一個字元。
$ 由游標所在位置至該行的最後一個字元。
0 由游標所在位置至該行的第一個字元。
) 由游標所在位置至下一個句子的第一個字元。
( 由游標所在位置至該句子的第一個字元。
{ 由游標所在位置至該段落的最後一個字元。
} 由游標所在位置至該段落的第一個字元。

整行動作
dd 刪除整行。
D 以行為單位,刪除游標後之所有字元。
cc 修改整行的內容。
yy yank整行,使游標所在該行複製到記憶體緩衝區。

.刪除與修改
===========
x 刪除游標所在該字元。
X 刪除游標所在之前一字元。
dd 刪除游標所在該行。
r 用接於此指令之後的字元取代(replace)游標所在字元。
如: ra 將游標所在字元以 a 取代之。
R 進入取代狀態,直到《ESC》為止。
s 刪除游標所在之字元,並進入輸入模式直到《ESC》。
S 刪除游標所在之該行資料,並進入輸入模式直到《ESC》。

.搬移與複製
==========
利用 delete 及 put 指令可完成資料搬移之目的。
利用 yank 及 put 指令可完成資料複製之目的。
yank 和 delete 可將指定的資料複製到記憶體緩衝區,而藉由 put 指令
可將緩衝區內的資料複製到螢幕上。
例:
搬移一行 ‧在該行執行 dd
‧游標移至目的地
‧執行 p
複製一行 ‧在該行執行 yy
‧游標移至目的地
‧執行 p

.指令重複
=========
在指令模式中,可在指令前面加入一數字 n,則此指令動作會重複執行 n
次。
例:
刪除10行 ‧10dd
複製10行 ‧10yy
‧游標移至目的地
‧p
指標往下移10行 ‧10j

.取消前一動作(Undo)
===================
即復原執行上一指令前的內容。

u 恢復最後一個指令之前的結果。
U 恢復游標該行之所有改變。

.搜尋
=====
在vi中可搜尋某一字串,使游標移至該處。

/字串 往游標之後尋找該字串。
?字串 往游標之前尋找該字串。
n 往下繼續尋找下一個相同的字串。
N 往上繼續尋找下一個相同的字串。

.資料的連接
===========
J 句子的連接。將游標所在之下一行連接至游標該行的後面。

若某行資料太長亦可將其分成兩行,只要將游標移至分開點,進入輸入模式
(可利用 a、i等指令)再按《Enter》即可。

.環境的設定
===========
:set nu 設定資料的行號。
:set nonu 取消行號設定。
:set ai 自動內縮。
:set noai 取消自動內縮。

自動內縮(automatic indentation)
在編輯文件或程式時,有時會遇到需要內縮的狀況,『:set ai』即提供自
動內縮的功能,用下例解釋之:
‧vi test
‧(進入編輯視窗後)
this is the test for auto indent
《Tab》start indent ← :set ai (設自動內縮)
《Tab》data
《Tab》data
《Tab》data ← :set noai (取消自動內縮)
the end of auto indent.
‧註:[Ctrl][d] 可刪除《Tab》字元。

.ex指令
=======
讀寫資料
:w 將緩衝區的資料寫入磁碟中。
:10,20w test 將第10行至第20行的資料寫入test檔案。
:10,20w>>test 將第10行至第20行的資料加在test檔案之後。
:r test 將test檔案的資料讀入編輯緩衝區的最後。

刪除、複製及搬移
:10,20d 刪除第10行至第20行的資料。
:10d 刪除第10行的資料。
:%d 刪除整個編輯緩衝區。
:10,20co30 將第10行至第20行的資料複製至第30行之後。
:10,20mo30 將第10行至第20行的資料搬移至第30行之後。

字串搜尋與取代
s(substitute)指令可搜尋某行列範圍。
g(global)指令則可搜尋整個編輯緩衝區的資料。
s指令以第一個滿足該條件的字串為其取代的對象,若該行有數個滿足該條
件的字串,也僅能取代第一個,若想取代所有的字串則需加上g參數。
:1,$s/old/new/g 將檔案中所有的『old』改成『new』。
:10,20s/^/ / 將第10行至第20行資料的最前面插入5個空白。
:%s/old/new/g 將編輯緩衝區中所有的『old』改成『new』。

.恢復編輯時被中斷的檔案
=======================
在編輯過程中,若系統當掉或連線中斷,而緩衝區的資料並還未
被寫回磁碟時,當再度回到系統,執行下列指令即可回復中斷前
的檔案內容。
%vi -r filename

.編輯多個檔案
=============
vi亦提供同時編輯多個檔案的功能,方法如下:
%vi file1 file2 ..

當第一個檔案編修完成後,可利用『:w』將該緩衝區存檔,而後
再利用 『:n』載入下一個檔案。

執行
=============
:!ls
:!php abc.php
可以直接執行程式
:sh
可以直接到 shall 模式