在Windows中我們可以通過快捷鍵 ctrl + c 複製,ctrl + v 貼上,在 linux 中需要使用命令。
cp
就是 copy 的意思。請看範例:
// 將 a.txt 複製一份,重新命名為 b.txt
test11@pj-pc:~$ cp a.txt b.txt
test11@pj-pc:~$ ls
模板 桌面 a.txt b.txt dir1
// 將 a.txt 複製到 dir1 目錄中
test11@pj-pc:~$ cp a.txt dir1
test11@pj-pc:~$ ls dir1
a.txt
// 將 dir1/a.txt 複製到當前目錄
test11@pj-pc:~$ cp dir1/a.txt .
如果當前目錄有同名的檔案,需要詢問是否覆蓋,可以使用引數 -i
:
// -i 會詢問是否覆蓋
test11@pj-pc:~$ cp -i dir1/a.txt .
cp:是否覆蓋'./a.txt'? n
test11@pj-pc:~$ rm a.txt
// 沒有同名檔案,則無需詢問
test11@pj-pc:~$ cp -i dir1/a.txt .
test11@pj-pc:~$
資料夾的拷貝需要使用引數 -r
,否則會提示錯誤:
// 報錯:缺少 -r
test11@pj-pc:~$ cp dir1 dir2
cp: 未指定 -r;略過目錄'dir1'
// 拷貝目錄
test11@pj-pc:~$ cp -r dir1 dir2
test11@pj-pc:~$ ls
模板 桌面 dir1 dir2
拷貝檔案比較清晰,而拷貝資料夾就沒那麼好理解,我們分幾種情況詳細介紹:
// 將 dir1 資料夾拷貝到 dir2目錄中
test11@pj-pc:~/dir$ cp -r dir1 dir2
test11@pj-pc:~/dir$ ls dir2
c.txt dir1
test11@pj-pc:~/dir$
// tree 可通過包管理器安裝
test11@pj-pc:~/dir$ tree
.
├── a.txt
├── dir1
│ └── b.txt
└── dir2
└── c.txt
2 directories, 3 files
// 將dir1資料夾中的內容拷貝到 dir2 中
test11@pj-pc:~/dir$ cp dir1/* dir2
test11@pj-pc:~/dir$ ls dir2
b.txt c.txt
將 dir1/a.txt
拷貝到當前目錄,以下兩種寫法一個有提示,一個沒有提示,是什麼原因?
test11@pj-pc:~/dir$ tree
.
├── a.txt
├── dir1
│ ├── a.txt
│ └── b.txt
└── dir2
├── b.txt
└── c.txt
2 directories, 5 files
// 沒有提示
test11@pj-pc:~/dir$ \cp dir1/a.txt .
// 有提示
test11@pj-pc:~/dir$ cp dir1/a.txt .
cp:是否覆蓋'./a.txt'? y
通過 alias
命令我們得知 cp 其實等同於 cp -i
,所以有提示,而 \cp
表示不使用別名,表示純 cp 命令。
test11@pj-pc:~/dir$ alias
alias cp='cp -i'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
alias ls='ls --color=auto'
Tip:alias 顯示當前定義的別名。建立一個新的別名 alias ll='ls -l'
,刪除一個別名 unalias ll
刪除檔案和目錄需要使用 rm
命令。
檔案直接即可刪除:
test11@pj-pc:~/dir$ ls
a1.txt a2.txt a3.txt dir1 dir2
// 刪除檔案
test11@pj-pc:~/dir$ rm a1.txt
// -i 刪除前確認
test11@pj-pc:~/dir$ rm -i a2.txt
rm:是否刪除普通空檔案 'a2.txt'?n
test11@pj-pc:~/dir$
刪除資料夾需要使用 -r
引數,否則報錯:
// 報錯:需要使用 -r
test11@pj-pc:~/dir$ rm dir1
rm: 無法刪除'dir1': 是一個目錄
// 刪除目錄
test11@pj-pc:~/dir$ rm -r dir1
test11@pj-pc:~/dir$ ls
a2.txt a3.txt dir2
// 刪除前確認
test11@pj-pc:~/dir$ rm -ir dir2
rm:是否進入目錄'dir2'? y
rm:是否刪除普通空檔案 'dir2/c.txt'?y
rm:是否刪除普通空檔案 'dir2/b.txt'?y
rm:是否刪除目錄 'dir2'?y
test11@pj-pc:~/dir$ ls
a2.txt a3.txt
Tip: 一名合格的運維工程師在修改檔案之前需要對原始檔(資料夾)進行備份
。否則一旦改錯,又改不回去,就很麻煩。
比如知道檔案或資料夾的名字,但忘記在哪裡,可以使用 find
命令。
// 在當前目錄中查詢名字是 dir2 的檔案或名錄
test11@pj-pc:~/dir$ find . -name dir2
./dir1/dir2
./dir2
ls 顯示的是非隱藏檔案(資料夾),如果需要檢視隱藏檔案
(資料夾),可以增加引數 -a
:
test11@pj-pc:~/dir$ ls
a3.txt dir1
// 顯示隱藏檔案和隱藏目錄
test11@pj-pc:~/dir$ ls -a
// . 當前目錄
// .. 上一層目錄
. .. .a2.txt a3.txt dir1 .dir2
隱藏檔案(資料夾)以點(.
)開頭,也是一種保護機制。
隱藏檔案檢視方式和普通檔案相同:
test11@pj-pc:~/dir$ cat .a2.txt
apple
如果需要將隱藏檔案或隱藏目錄轉成非隱藏,重新命名(刪除.)即可。
test11@pj-pc:~/dir$ mv .a2.txt a2.txt
test11@pj-pc:~/dir$ mv .dir2 dir2
// a2.txt 和 dir2 不在隱藏
test11@pj-pc:~/dir$ ls
a2.txt a3.txt dir1 dir2
我們現在一直圍繞著檔案學習 linux 命令,為什麼總是圍繞檔案?因為 Linux 中一切皆檔案。
筆者的 linux 有一塊磁碟 /dev/sda
931G。
/dev/sda
是一個檔案,用它來表示硬碟。
// fdisk -l 檢視本地磁碟資訊
pj@pj-pc:/home/test11/dir$ sudo fdisk -l
Disk /dev/sda:931.53 GiB,1000204886016 位元組,1953525168 個磁區
Disk model: WDC WD10EZEX-75W
單元:磁區 / 1 * 512 = 512 位元組
...
這個檔案和其他檔案一樣,也有自己的屬性:
pj@pj-pc:/home/test11/dir$ ls -l /dev/sda
brw-rw---- 1 root disk 8, 0 7月 17 14:52 /dev/sda
最前面的一位 b,b=block
,也就是塊裝置,說白了就是硬碟。
於是我們知道在 linux 中,用檔案表示各種東西。
登陸後預設來到使用者的家目錄,但對於 linux 來說,家目錄不是不是最原始的起點。
Linux 下所有目錄最開始的起點叫做「根」,也就是/
。所有目錄都以它為起點,如樹杈一樣,一層一層向下擴充套件。
感覺根有點虛,其實是可以看見的:
pj@pj-pc:~$ ls /
backup bin boot cdrom data dev etc home lib lib32 lib64 libx32 lost+found media mnt opt proc root run sbin srv sys tmp usr var
這裡顯示的就是一級目錄,不同發行版,一級目錄都差不多(目錄名)
pj@pj-pc:~$ tree -L 1 /
/
├── backup
├── bin -> usr/bin
├── boot
├── cdrom
├── data
├── dev
├── etc
├── home
├── lib -> usr/lib
├── lib32 -> usr/lib32
├── lib64 -> usr/lib64
├── libx32 -> usr/libx32
├── lost+found
├── media
├── mnt
├── opt
├── proc
├── root
├── run
├── sbin -> usr/sbin
├── srv
├── sys
├── tmp
├── usr
└── var
25 directories, 0 files
如果一個路徑從 / 開始,例如 "/home/user1/xx" 就是一個絕對路徑。
接下來我們得真正用 linux 乾點活了。
主管
:來了2個新人,你(運維工程師)給他們在伺服器A中給他們建立賬號並郵件通知他們(省去許多其他要求...)
在 windows 中,給使用者建立賬號,最好是管理員角色。在 linux 中不叫管理員
,而是 root
,也是一個特殊的使用者。
root 在 linux 中擁有最高的許可權,無所不能。所以公司通常會加以限制,root賬戶只對少數人開放(其他人不允許用root登入),例如運維工程師,為了伺服器和系統的穩定需要隨時擁有最高許可權。
通過 whoami
檢視當前使用者:
pj@pj-pc:~$ whoami
user-pj
Tip: 筆者沒有測試伺服器的 root 賬號。
用 useradd
建立使用者(sudo 讓普通使用者臨時擁有root的許可權),並通過 id 檢視使用者是否真的被建立出來:
// 建立一個叫 test18 的使用者
pj@pj-pc:~$ sudo useradd test18
// 使用者建立成功
pj@pj-pc:~$ id test18
uid=1005(test18) gid=1005(test18) 組=1005(test18)
pj@pj-pc:~$
Tip:adduser 和 useradd 功能類似,但有一些區別。adduser 是一個高階的使用者管理工具;而 useradd 更基本,比如 useradd 不會建立家目錄;
root 不是角色,而是一個實實在在的使用者。雖然 root 使用者只有一個,但是通過許可權和分組,可以讓普通使用者擁有root一樣高的許可權。
// 建立一個叫 root 的使用者
pj@pj-pc:~$ sudo useradd root
輸入密碼
useradd:使用者「root」已存在
現在我們建立了 test18 使用者,接下來得給他分配密碼。通過 passwd 給使用者建立密碼:
pj@pj-pc:~$ sudo passwd test18
新的密碼:
// linux 中密碼有一定規範
無效的密碼:密碼少於 8 個字元
新的密碼:
無效的密碼:密碼包含的字元型別少於 2 種
新的密碼:
重新輸入新的密碼:
passwd:已成功更新密碼
Tip: 如果你使用root給新使用者建立密碼,即使使用一個不符合規則
的密碼,也能建立成功,因為 root 有最高許可權。
如果需要切換使用者登入,可以使用 su - 使用者名稱
:
pj@pj-pc:~$ su - test18
輸入密碼
$
// 再次確定是否切換成功
$ whoami
test18
$ id
uid=1006(test18) gid=1006(test18) 組=1006(test18)
$
登入後修改自己的密碼,直接輸入 passwd
即可:
$ passwd
為test18更改密碼
當前密碼:
新的密碼:
無效的密碼:與舊密碼相同
新的密碼:
前面我們已經對linux 賬號有所瞭解(root、普通使用者),這裡我們在認識一下系統賬號
。
系統賬號不是給人用的,而是給程式用的。系統賬號長什麼樣子?比如 mail:
pj@pj-pc:~$ id mail
uid=8(mail) gid=8(mail) 組=8(mail)
系統賬號安裝軟體時,程式自動建立的。例如現在沒有ntp賬號,安裝 ntp 只有就有該賬號了:
// 沒有 ntp 賬號
pj@pj-pc:~$ id ntp
id: 「ntp」:無此使用者
// 安裝 ntp
pj@pj-pc:~$ sudo apt install ntp
正在讀取軟體包列表... 完成
正在分析軟體包的依賴關係樹
...
// 有 ntp 賬號
pj@pj-pc:~$ id ntp
uid=124(ntp) gid=132(ntp) 組=132(ntp)
系統賬號不能拿來直接使用,而是軟體執行時,由它們自己來使用。
Tip:約定Uid小於1000的是系統賬號。
只是學會用命令建立賬號、修改密碼,這是最基本的入門。
我們要深入探索 Linux 使用者賬號,先學習使用者賬號的管理。
要掌握 linux 使用者管理,首先得知道全部使用者都定義在哪裡。如下操作:
pj@pj-pc:~$ head /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
/etc
目錄放置的都是組態檔,全部使用者就定義在 /etc/passwd
組態檔中。
這些都是使用者:root、daemo、bin...
pj@pj-pc:~$ id root
uid=0(root) gid=0(root) 組=0(root)
pj@pj-pc:~$ id daemon
uid=1(daemon) gid=1(daemon) 組=1(daemon)
pj@pj-pc:~$ id bin
uid=2(bin) gid=2(bin) 組=2(bin)
先來認識一下什麼是組態檔
?
我們的 linux 上面執行著各種各樣的軟體,軟體到了底層,就是程式在執行。
如果想改變程式的執行方式,直接跟程式說沒用,因為程式不接受你的直接調遣。如果你通過組態檔
讓其改變,程式就會乖乖就範。
上文我們學習的使用者管理,背後也是有對應的程式在執行。
我們直接通過命令 useradd 建立使用者,根本沒有接觸組態檔,其實這是表象。做一個試驗就知道了。我們直接修改 /etc/passwd
模仿 test18 增加一條資料:
pj@pj-pc:~$ id test19
id: 「test19」:無此使用者
pj@pj-pc:~$ tail -n 2 /etc/passwd
test18:x:1006:1006::/home/test18:/bin/sh
test19:x:1007:1007::/home/test19:/bin/sh
使用者(test19)建立成功:
// 不一樣
pj@pj-pc:~$ id test19
uid=1007(test19) gid=1007 組=1007
pj@pj-pc:~$ id test18
uid=1006(test18) gid=1006(test18) 組=1006(test18)
這樣編輯一下 /etc/passwd 建立建立出來的使用者,是不完整
的,缺少一些東西,接下來將圍繞這個遺留問題,繼續操作和講解。
使用者 test18 使用useradd 命令建立,而 test19 是直接編輯組態檔建立的。通過 id 就會發現有所不同:
pj@pj-pc:~$ id test18
uid=1006(test18) gid=1006(test18) 組=1006(test18)
// gid=1007(缺少) 組=1007(缺少)
pj@pj-pc:~$ id test19
uid=1007(test19) gid=1007 組=1007
為了講清楚這部分差異,我們下面分幾個步驟。
在linux中,每個使用者必須屬於一個組織,這個組織就是主組(gid
)和附屬組(groups
,筆者這裡就是組
)。
以 test18 為例,gid=1006(test18)
其主組是 test18,組=1006(test18)
附屬組也是 test18。
當執行 useradd,系統會給 test18 建立一個同名的組 test18,並讓該使用者的主組是它。
主組只有一個,附屬組可以沒有或者有多個。下面我們給 test18 增加一個附屬組(usermod -aG
):
// 通過 usermod 給 test18 增加一個附屬組
pj@pj-pc:~$ sudo usermod -aG mail test18
輸入密碼
pj@pj-pc:~$ id test18
uid=1006(test18) gid=1006(test18) 組=1006(test18),8(mail)
pj@pj-pc:~$
組在哪裡定義的,我們可以自己建立嗎?
pj@pj-pc:~$ cat /etc/group |grep 'test18'
mail:x:8:test18
test18:x:1006:
/etc/group
組態檔中定義了所有的組,其中使用者test18的主組gid=1006(test18)
就在其中:
pj@pj-pc:~$ id test18
uid=1006(test18) gid=1006(test18) 組=1006(test18),8(mail)
而 test19 對應的組 1007 根本不存在
pj@pj-pc:~$ id test19
uid=1007(test19) gid=1007 組=1007
給組態檔增加一行(test19:x:1007:
):
pj@pj-pc:~$ cat /etc/group |egrep "test18|test19"
mail:x:8:test18
test18:x:1006:
// 增加這一行(shift+g定位到最後一行)
test19:x:1007:
這樣就顯示正常了:
pj@pj-pc:~$ id test19
uid=1007(test19) gid=1007(test19) 組=1007(test19)
pj@pj-pc:~$
我們在看下面段程式碼,1007:1007
是什麼?
pj@pj-pc:~$ cat /etc/passwd |egrep "test18|test19"
test18:x:1006:1006::/home/test18:/bin/sh
test19:x:1007:1007::/home/test19:/bin/sh
前一個1007表示系統分配給使用者 test19 的 ID,不可以隨便改變,後一個1007是主組ID
。
Tip:在Linux使用者管理系統中,每個使用者和組都有一個唯一的數位識別符號(UID和GID)。雖然使用者名稱和組名更加易於人類理解,但實際上,系統在內部使用對應的數位
來識別使用者和組。
做一個小實驗,看主組能否改變。
將 test19 的主組id改成test18的主組id:
pj@pj-pc:~$ tail -n 2 /etc/passwd
test18:x:1006:1006::/home/test18:/bin/sh
test19:x:1007:1006::/home/test19:/bin/sh
真的改成功了,現在 test19 的使用者組是 test18:。
pj@pj-pc:~$ id test19
uid=1007(test19) gid=1006(test18) 組=1006(test18)
我們再做一個實驗,如果一個使用者,一個組都不屬於會怎麼樣?
pj@pj-pc:~$ tail -n 2 /etc/passwd
test18:x:1006:1006::/home/test18:/bin/sh
test19:x:1007:::/home/test19:/bin/sh
使用者資訊報錯:
pj@pj-pc:~$ id test19
id: 「test19」:無此使用者
我們編輯組態檔建立了 test19,前文已經知道 1007:1007
的含義:
test19:x:1007:1007::/home/test19:/bin/sh
現在再來看一下 /home/test19
,表示test19的家目錄。
pj@pj-pc:~$ ls /home/test19
ls: 無法存取'/home/test19': 沒有那個檔案或目錄
既然沒有這個目錄,我們自己建立:
// 建立目錄
pj@pj-pc:~$ sudo mkdir /home/test19
pj@pj-pc:~$ ls -l /home
drwxr-xr-x 2 root root 4096 7月 18 15:08 test19
// 將 /home/test19 目錄及其所有子目錄和檔案的所有者和所屬群組都修改為 test19
pj@pj-pc:~$ sudo chown -R test19:test19 /home/test19
pj@pj-pc:~$ ls -l /home
drwxr-xr-x 2 test19 test19 4096 7月 18 15:08 test19
Tip:chown 用於修改許可權,後面會講到。
現在路徑是/home/demo
,切換 test19 登入後,自動進入對應的家目錄:
pj@pj-pc:~$ pwd
/home/demo
pj@pj-pc:~$ su - test19
輸入密碼
$ pwd
/home/test19
$
Tip: 這裡如果使用 su test19
,則不會進入該使用者的家目錄。su -
和 su
是兩個命令,su -
會同時載入該使用者的所有環境變數和組態檔。
所謂登入,到底是登入什麼?
有同學說是 linux。對也不對!linux前文我們說是 linux 核心,是深不見底的東西。是有什麼東西在協助我們?
是 Shell。表示 linux 核心外的一層殼。而 bash 是最知名的一種 shell。
現在 test19 最後一個欄位是 /bin/bash
,表示該使用者登入後,給他 bash。
test19@pj-pc:~$ tail -3 /etc/passwd
test19:x:1007:1007::/home/test19:/bin/bash
// 當前所使用的 shell 的路徑
test19@pj-pc:~$ echo $SHELL
/bin/bash
// 輸出當前 shell 的名稱
test19@pj-pc:~$ echo $0
-bash
Tip:/bin
目錄下還有許多常用命令,比如vi,所有使用者都可以使用。
如果你將 test19 的 /bin/bash
改成 /bin/vi
,登入後就不會給bash,而是vi
,感興趣的同學可以試一下。
我們還看到:
ntp:x:124:132::/nonexistent:/usr/sbin/nologin
nologin 就是禁止登入,我們將其分配給 test19 看看會怎麼樣?
// sbin 就是 usr/sbin(sbin -> usr/sbin)
test19:x:1007:1007::/home/test19:/sbin/nologin
使用者無法登入
pj@pj-pc:~$ su - test19
輸入密碼
// 這個帳號當前不可用
This account is currently not available.
Tip:不建議將 root 設定成這種登入方式,對於初學者比較麻煩。
前面我們用 su 切換使用者,相等於登出當前使用者,換一個使用者來使用。
在日常中,較少使用 su,更多是使用 sudo
。
普通使用者直接檢視 /root 不允許:
$ ls /root
ls: 無法開啟目錄'/root': 許可權不夠
臨時使用 root 的使用者執行 ls /root
test19@pj-pc:~$ sudo -u root ls /root
模板 桌面
test19@pj-pc:~$ whoami
test19
Tip:直接使用 sudo 可能提示不在 sudoers 檔案中
,需要通過 visudo
命令修改 sudo 組態檔
test19@pj-pc:~$ sudo ls /root
輸入密碼
test19 不在 sudoers 檔案中。此事將被報告。
pj@pj-pc:~$ sudo visudo
root ALL=(ALL:ALL) ALL
// 增加一行
// <使用者名稱> <主機名>=(<身份>:<終端>) <命令>
test19 ALL=(ALL:ALL) ALL
指定了 test19 使用者在任何主機、以任何使用者身份、在任何終端上都可以使用 sudo 命令
前面我們通過編輯組態檔 /etc/passwd 建立使用者,我們也知道用 passwd 給使用者建立密碼。
密碼沒有存在 /etc/passwd,而是在 /etc/shadow
中,加密之後儲存的。例如搜尋使用者 test19 的密碼:
pj@pj-pc:~$ sudo cat /etc/shadow |grep 'test19'
test19:$6$7ZkiOkEth7bdStHU$GWt/YVaD/KlJ5b21afWhqXPECRDj5tDmNBx.TDKW 6M2jd1jvtMlYFcrGVoWsmSkJ5hnIaEQyI8nLs4PDNJOm4.:19556::::::
雖然密碼並不是使用 md5sum 加密,但我們可以使用其模擬一下:
// 輸入不變,輸出也不變
pj@pj-pc:~$ echo -n '123456' | md5sum
e10adc3949ba59abbe56e057f20f883e -
pj@pj-pc:~$ echo -n '123456' | md5sum
e10adc3949ba59abbe56e057f20f883e -
pj@pj-pc:~$
機器就在身邊是本地登入,更多的是遠端登入。
無論是本地登入還是遠端登入,都是 linux 本地賬號密碼
在一個系統中,如果兩個使用者都使用 root 身份進行登入,一個是本地登入,另一個是遠端登入,那麼它們之間可能會互相不知道對方的存在。這種情況下可以被看作是一種多使用者管理模式,其中每個使用者都以獨立的身份登入並執行各自的操作。