上个月在一台新装的 Ubuntu 上配训练环境,前面三天全耗在基础操作上:装完系统没有 root 密码、apt 装完命令还是找不到、脚本丢进定时任务一声不响。显卡驱动反倒是最顺的一步。这篇把那段敲过的命令和查出来的原因记一遍,给同样刚上手 Ubuntu 的人看。
一、Linux 跟 Windows 不一样的地方
我一开始拿 Windows 的习惯套 Linux,处处别扭。后来发现差别就三条。
Linux 里一切皆文件。硬盘、网卡、进程信息都是文件,能用同一种方式读。这也解释了 /dev 和 /proc 为什么长得奇怪:它们不是目录,是设备和内核状态以目录的形式露出来。
没有盘符,只有一棵树。所有东西从 / 开始往下挂,插一块硬盘也是挂到树上的某个点,而不是多出一个 E 盘。
默认不是管理员。Windows 装完系统你就是管理员,Linux 上你只是个普通用户,改系统级的东西要显式提权。多一步麻烦,换来手滑时有个刹车。
二、目录结构
刚上手最容易犯的错是装完软件找不到它装在哪了。下面这些记住就够用,其余碰到再查。
| /etc | 系统和软件的配置文件 | 改配置、换软件源、改主机名 |
| /home | 普通用户的家目录 | 登录后默认就在这 |
| /root | root 用户的家目录 | 切到 root 才进得去 |
| /usr | 用户级应用和文件,类似 Program Files | 自己装的应用多半在这 |
| /opt | 第三方的、可选的大型软件 | Anaconda 这类我习惯放这 |
| /var | 经常变的数据,日志是大头 | /var/log 是查问题的第一站 |
| /tmp | 临时文件,过一阵自动清 | 试验脚本丢这,重启可能就没了 |
| /dev | 设备文件 | 看磁盘、看终端 |
| /proc | 内核和进程的虚拟映射 | 只读,用来取系统信息 |
| /mnt、/media | 挂载点 | 插 U 盘、挂数据盘 |
| /boot | 启动用的核心文件 | 自己的东西别往这放 |
| /lib | 最基本的动态库,类似 Windows 的 DLL | 基本不手动改 |
| /bin、/sbin | 常用命令和系统管理命令 | 其实是 /usr/bin、/usr/sbin 的软链接 |
我找东西的顺序是:配置去 /etc,日志去 /var/log,自己的东西在 /home,软件装在 /opt 或者 /usr。按这个想,八成能猜对位置。
三、远程登录
公司的机器和云主机都不会让你坐到跟前去,全靠远程。常见的是 Xshell、SecureCRT、FinalShell,配 Xftp 传文件。Ubuntu 上装了 SSH 服务之后一条命令就进去。
ssh 用户名@服务器IP
我用 Xshell 会同时开几个标签页,一个挂日志、一个改文件、一个跑命令,比在同一个窗口里反复 cd 省事。传文件一般用 scp 或者 Xftp 拖,路径不容易敲错。
四、用 apt 装东西
apt 是 Debian 系(Ubuntu 属于这一支)的包管理工具,下载、解依赖、安装一条龙。日常就用这几条。
sudo apt update # 拉新"有哪些包、什么版本"的清单
sudo apt install net-tools # 装包,加 -y 跳过确认
sudo apt remove net-tools # 卸载,保留配置
sudo apt search net-tools # 搜包
sudo apt show net-tools # 看包详情
有两处我一开始就理解错了。apt update 只是把清单拉新,不动已经装好的软件;要升级得用 apt upgrade,两个命令。第一次装环境时我拿 update 当升级,白等半天。
另外如果 ifconfig 提示 command not found,不是命令被删了,是新版 Ubuntu 默认不带 net-tools,装一下就有。这个我至少帮三个人查过。
remove 和 purge 也不一样:remove 会留下配置文件,purge 连配置一起删。要彻底重装某个服务,只 remove 有时会带着旧配置起来,加上 purge 才干净。
五、命令忘了怎么查
命令记不住很正常,会查就行。man 查手册,手册按章节分:第 1 节是用户命令,第 2 节是系统调用,第 3 节是库函数,第 7 节是杂项和规范。同名的东西可能散在不同章节。
man ls # 查 ls
man 2 write # 查第 2 节的 write;man write 查的是第 1 节的用户命令
man -k 关键词 # 按关键字找相关手册
如果提示"在第 2 节中没有关于 write 的手册条目",不是敲错了,是手册页包不全,装一下就好。
sudo apt install manpages manpages-dev
还有一类是 shell 自带的命令,比如 cd、echo,它们没有独立的可执行文件,也就没有手册页,得用 help 查。
help # 列出所有内建命令
help cd # 查 cd
几个快捷键值得早点养成肌肉记忆:Ctrl+L 清屏,Ctrl+C 中断当前进程,Ctrl+U 把敲了一半的命令整行删掉,Tab 补全路径,上下方向键翻历史。Tab 用得最多,路径敲一半按一下,补不上说明前面哪里错了,等于免费查一次错。
六、文件和目录的日常操作
看自己在哪
pwd # 当前目录的绝对路径
ls # 列目录
ls -a # 连隐藏文件一起列,. 开头的就是隐藏文件
ls -l # 长格式:权限、属主、属组、大小、时间、名称
ls -lh # 大小换成 K/M/G,看着舒服
ls -R # 递归往下列
Ubuntu 上 ll 是 ls -al 的别名,我平时基本只用 ll 和 ls -lh。长格式那一行从左往右看:文件类型和权限、链接数、属主、属组、大小(字节)、最后修改时间、名字。
换目录
cd /bin # 绝对路径
cd 公共的/ # 相对路径
cd # 或 cd ~,回家目录
cd – # 回上一次待的目录,两个目录来回跳很省事
cd .. # 上一级
cd -P 软链接 # 进软链接指向的真实路径
建、删、复制、移动
mkdir test # 建目录
mkdir -p test/b/bb/bbb # 一次建多层,父目录不存在也不报错
touch test/a/note.txt # 建空文件,也可以用来更新时间戳
cp note.txt test/b/ # 复制文件
cp -r test/b/ ./ # 复制目录得加 -r
mv old.txt new.txt # 重命名
mv new.txt ./ # 移动
rm b/note.txt # 删文件
rm -r b/ # 递归删目录
rm -rf b/ # 强制递归删,慎用
rm 没有回收站,删掉基本找不回来。我现在的习惯是删目录之前先 ls 看一眼,路径写全,不在根目录底下随手用 -rf。真要做危险操作,先写进脚本读一遍再跑,比在命令行上冲动回车强。
看文件内容
cat -n /etc/passwd # 小文件用它,-n 带行号
tail -n 2 文件 # 最后 2 行,默认 10 行
tail -F 日志文件 # 实时显示新追加的内容
tail -F 我几乎每天在用,注意是大写 F。它跟 -f 的区别是文件被轮转、重命名之后还能接着跟,-f 就断在那儿了。看日志时这个区别很要命。
echo 和重定向
echo "hello world"
echo -e "hello world" # 加 -e 才会解释反斜线转义
ls -l > note.txt # 覆盖写入
ls -l >> note.txt # 追加写入
echo hello >> note.txt
加 -e 之后才能用换行、制表这类转义写法,不加就原样打出来。单箭头覆盖,双箭头追加。有人想追加结果用了单箭头,一整份配置文件被一行 ls 输出顶掉,那台机器靠备份才救回来。改重要文件之前先 cp 一份,一秒钟的事。
软链接
ln -s test/a/note.txt ./ # 给文件建
ln -s test/b ./ # 给目录建
软链接就是 Windows 的快捷方式,ll 看第一位是 l,尾巴上有个箭头指向真实路径。两个小地方:删的时候用 rm 链接名或者 unlink,别在链接名后面挂 /,挂上就删不掉了;想进到真实的物理路径用 cd -P。
history
history
配合上下方向键和 !编号,长命令不用重敲。
七、vi / vim
vim 是 vi 的增强版,能按语法着色,改配置文件和写脚本都够用。第一次用我是懵的:打字打不上去,想退出也退不出来。问题不在命令多,是不清楚自己现在在哪个模式。
三个模式。打开文件默认在一般模式,这时候字母是命令不是文字,管移动、复制、删除、撤销。按 i、a、o 这类键进编辑模式,左下角出现 — INSERT — 才能打字。在一般模式下按 : 或者 / 进命令模式,存盘、退出、替换、显行号都在这里做。
我记的只有一句:慌就按 Esc。所有模式都能回到一般模式,多数"是不是弄坏了"的慌,其实是还停在编辑模式里。
一般模式常用的几个:
yy 复制当前行 y数字y 从当前行往下复制 n 行
p 粘贴 u 撤销
dd 删当前行 d数字d 从当前行往下删 n 行
x / X 删当前字符 / 删前一个字符
yw / dw 复制一个词 / 删一个词
^ / $ 跳到行首 / 行尾 gg / G 文件头 / 文件尾
数字N + G 跳到第 N 行
/关键词 搜索,n 下一个,N 上一个
进编辑模式的入口:i 光标前,a 光标后,o 当前行下面新起一行,I 行首,A 行尾,O 当前行上面新起一行。
存盘和退出:
:w 保存 :q 退出,没改过才能直接退
:q! 不保存强制退 :wq 保存退出,:x 也行
:set nu 显行号 :set nonu 关行号
:%s/old/new/g 全文替换
:noh 取消搜索高亮
有个救场的用法值得记:改配置文件忘了加 sudo,改完存不了。不用退出重来,在命令模式里执行下面这句,输一次密码就能把改动写回去,然后 :q! 退掉。
:w !sudo tee % >/dev/null
另外如果误按 Ctrl+S 发现终端不动了,其实是被暂停输出,按 Ctrl+Q 就恢复。第一次碰到我以为机器挂了,差点重启。
八、用户和用户组
装完 Ubuntu 只让我设一个普通用户的密码,没有 root 密码,我疑惑了一阵。后来知道 Ubuntu 默认把 root 锁着,不给密码,逼你用普通用户登录,需要高权限时用 sudo 临时提权。这比全程 root 稳妥,至少动手之前要过一道确认。
确实需要 root 环境的时候,比如要跑依赖某些环境变量的脚本,可以先给 root 设密码再切。
sudo passwd root # 给 root 设密码
su root # 切换,保留当前工作环境
su – root # 切换并加载 root 的完整环境变量
exit # 退出
sudo passwd -l root # 再锁上
sudo passwd -u root # 解锁
su 和 su – 的差别我一开始没在意,直到跑脚本报命令找不到才明白:su – 会连目标用户的环境变量和 PATH 一起带过来,su 只借权限不借环境。要做系统管理的事,直接 su – 少踩坑。
用户
useradd -m tangseng # 加 -m 才会建家目录
passwd tangseng # 设密码
id tangseng # 看 uid、gid 和所属组
cat /etc/passwd # 系统里都有哪些用户
userdel tangseng # 删用户,留家目录
userdel -r tangseng # 连家目录一起删
usermod -l 新名 老名 # 改用户名
usermod -d /home/新目录 -m 用户名 # 改家目录
useradd 不加 -m 不会建家目录,登进去没有自己的地方,很容易懵。Ubuntu 上我更喜欢 adduser,它一步一步问,家目录、骨架文件、密码一起配好;useradd 更底层,适合写进自动化脚本。
组
groupadd xitianqujing # 新增组
groupdel xitianqujing # 删组
groupmod -n xitian xitianqujing # 改组名
usermod -g xitian zhubajie # 换某个用户的主组
cat /etc/group # 系统里都有哪些组
组的增删改说到底是在改 /etc/group。想明白这点,"权限该给谁"就有答案了:手改文件容易改坏,用命令改,系统会替你检查格式。
给普通用户开 sudo
要临时给某个账号提权,在 /etc/sudoers 里加一行:
root ALL=(ALL) ALL
testu ALL=(ALL) ALL # 每次要输密码
testu ALL=(ALL) NOPASSWD:ALL # 不输密码
改完存盘,用 testu 重新登录就能 sudo 了。这里更推荐用 visudo 打开这个文件,它会做语法检查,写错了不让你保存。sudoers 语法写坏导致 sudo 直接不能用、只能进恢复模式,我见过不止一次。
九、权限
同一个文件对不同的人可以不一样待遇,靠的就是 ll 最左边那 10 个字符。第 0 位是类型:- 是普通文件,d 是目录,l 是软链接。第 1 到 3 位是属主,4 到 6 位是属组,7 到 9 位是其他人。
r、w、x 对文件和目录的意思不一样,这点最容易混。
| r | 能读内容 | 能 ls 列出里面有什么 |
| w | 能改内容,但不代表能删掉这个文件 | 能在里面新建、删除、改名 |
| x | 能被执行 | 能 cd 进去 |
那个 w 要留意:能不能删一个文件,看的是你对它所在目录有没有 w,不是对文件本身。这点我盯着权限位看了半天才想通。
chmod
chmod u+x passwd # 属主加执行
chmod g+x passwd # 属组加执行
chmod u-x,o+x passwd # 组合写
chmod 765 passwd # 7=rwx,6=rw-,5=r-x
chmod -R 777 test # 递归全开,非常不建议
数字法是 r=4、w=2、x=1 加起来。u、g、o 分别是属主、属组、其他人,a 是所有人。
777 我得多说一句。它基本等于"我搞不定权限了",不是解决办法:把目录开成 777,任何能登进这台机器的人都能改你的程序文件,共享机器上跟在门口蹲着没区别。我现在的顺序是先用 id 看清自己是谁、在哪个组,再看文件属于谁,然后要么 chown 改成自己,要么用 usermod -aG 组名 用户名 把自己加进对应的组,docker、www-data 常这么处理,要么只给刚够用的那点权限。
chown 和 chgrp
sudo chown root note.txt # 改属主
sudo chown -R root:root test/ # 递归改属主和属组
sudo chgrp zxf tt.txt # 只改属组
sudo chown $USER:$USER 文件名 # 改成自己
最后那条是个折中用法:某个配置文件天天要改,每次都 sudo 很烦,又不想开 777,可以把属主改成自己。但系统关键文件,比如 /etc/passwd、/etc/sudoers,别这么干,改属主可能让服务直接访问不了。
十、find 和 grep
find ./ -name "*.txt" # 按名字找,通配符要加引号
find ./ -user zxf # 按属主找
find ./ -size +200c # 按大小找,+ 大于、- 小于;b/c/w/k/M/G 是单位
find 是从指定目录往下递归遍历,范围给得越大越慢,别一上手就从 / 开始扫全盘。
grep 找的是"内容里含某个词的行",几乎总和管道符一起用。
grep -n 关键词 文件名 # -n 显示行号
ll | grep zx # 从命令输出里过滤
cat passwd | grep -n wu
管道 | 就是把前一条命令的输出交给后一条当输入。想通这点,很多看着很长很唬人的命令其实就是几个简单工具串起来:ps -ef | grep python 就是列出所有进程,再筛出带 python 的那些。
十一、tar 压缩解压
tar -zcvf tt.tar.gz tt.txt tt2.txt # 压多个文件
tar -zcvf test.tar.gz test/ # 压目录
tar -zxvf test.tar.gz # 解到当前目录
tar -zxvf test.tar.gz -C ./work # 解到指定目录
参数记两个组合就够:打包 -zcvf,解包 -zxvf。c 是 create,x 是 extract,z 是 gzip,v 是显示过程,f 是指定文件名。有一点要注意,f 后面紧跟的一定是压缩包名,所以 -zcvf 要写在最前面、包名紧跟其后,顺序错一位就报错。
十二、磁盘和网络
df -h # 各分区用了多少、还剩多少
du -a 目录/文件 # 看具体文件和目录占多大
ifconfig # 看网络接口和 IP
ping 目的主机 # 测连通性
hostname # 看主机名
服务起不来我先看 df -h。磁盘写满之后日志写不进去、数据库拒绝写入,报出来的错完全不像磁盘问题,很容易查错方向。确认满了,再用 du -a 往下找是哪个目录吃的。
网络不通先 ifconfig 看有没有 IP,再 ping 网关和外网域名。IP 能通、域名不通,那就是 DNS 的事。
改主机名:临时改是 hostnamectl set-hostname,要永久生效得改 /etc/hostname,改完重启或者重新登录才看得到。/etc/hosts 里的映射顺手对一下,不然本地解析会对不上。
十三、进程
ps -aux # 所有进程,重点看 %CPU、%MEM
ps -ef # 带父进程 PPID,看谁拉起了谁
free -m # 内存总览
top # 实时看系统状态
top -d 1 # 每 1 秒刷新
top -p 3933 # 只盯某个进程
kill -9 进程号 # 强制杀
killall 进程名 # 按名字杀,精确匹配
netstat -nlp | grep 端口号 # 端口被谁占用
netstat -anp | grep 进程号 # 某进程的网络连接
ps -aux 看资源占用,ps -ef 看父子关系。ps -aux 里 STAT 那列值得扫一眼:R 运行、S 睡眠、T 停止、s 含子进程、+ 在前台、I 基本不占 CPU。出现一堆 D,也就是不可中断睡眠,或者僵尸进程,说明 I/O 或进程回收出了问题。
top 里我先看三处:第一行的 load average,1、5、15 分钟平均负载,长期高过核数就是过载;第三行的空闲率 %id;第四行 Mem 的 available。按 P 依 CPU 排,M 依内存排,q 退出。
杀进程先发默认信号,也就是 15,通知它自己退出,等几秒还在再 -9。直接 -9 进程没机会保存数据和清临时文件,数据库类的进程尤其危险。killall 按进程名精确匹配,名字错一位就没反应,反倒不容易误杀。
十四、basename 和 dirname
basename /home/zxf/note.txt # 得到 note.txt
basename /home/zxf/tt.txt .txt # 去掉后缀,得到 tt
dirname /home/zxf/banzhang.txt # 得到 /home/zxf
单独用没什么意思,写脚本时顺手。脚本里要取自己所在目录就一行:
DIR=$(dirname "$0")
这样不管从哪个路径调用,脚本都能找到自己的位置,后面引用同目录的文件不会出错。
十五、crontab
cron 是系统自带的定时任务,Ubuntu 上叫 cron,CentOS 上叫 crond。先看服务在不在。
sudo systemctl restart cron
systemctl status cron
五个星号依次是分钟(0-59)、小时(0-23)、日(1-31)、月(1-12)、星期(0-7,0 和 7 都是周日)。
crontab -e # 编辑
crontab -l # 查看
crontab -r # 删掉当前用户的全部任务
| * | 任意时间 | 第一个 * 就是每分钟 |
| , | 不连续的几个点 | 0 8,12,16 * * * 每天 8、12、16 点整 |
| – | 连续范围 | 0 5 * * 1-6 周一到周六凌晨 5 点 |
| */n | 每隔多久 | */10 * * * * 每 10 分钟 |
比如每分钟往文件里追加一个 11:
*/1 * * * * /bin/echo "11" >> /opt/module/bailongma.txt
语法不难,难的是写完不执行。这事我踩过,也帮别人查过几次,原因基本就那几个。
PATH 太干净。cron 跑起来的 PATH 通常只有 /usr/bin:/bin,也不读 .bashrc,你在终端里随手能敲的 python、conda、docker,在 cron 里找不到。要么命令全写绝对路径,要么在文件顶上显式声明 PATH。
工作目录不是你以为的那个。cron 的当前目录是家目录,不是脚本所在的地方,脚本里写相对路径读写文件一定找不到,开头先 cd 过去。
输出被丢了。cron 会把输出发给本地邮件,服务器大多没配邮件,于是看起来什么都没发生。每条任务后面加 >> /var/log/xxx.log 2>&1,出错自己会说话。
权限和属主不对。脚本要 chmod +x,第一行要有对的 shebang,任务要写在真正要执行它的那个用户的 crontab 里。
% 是特殊字符。crontab 里 % 会被当成换行,date +%F 得写成 date +\\%F。这个最阴,日志里只告诉你命令被截断了。
时区或者服务本身的问题。云主机和容器里的时区常和本地不一样;cron 服务没启动更是啥都不会发生。
现在我调试固定三步:先放一条 * * * * * date >> /tmp/cron_test.log,确认 cron 到底有没有在触发;再看 /var/log/syslog 里有没有 CRON 的 CMD 记录;最后才把真脚本放进去。先证明调度到了,再查脚本里面为什么失败,省很多瞎猜。
几件我想早点知道的事
不要长期用 root 干活。sudo 多敲几下不麻烦,删错一个目录才麻烦。
改配置之前先 cp 一份,一秒钟的事,能省一整天。改 sudoers 用 visudo,别直接 vi。
重定向看清是一个箭头还是两个。vi 里出不来先按 Esc 再 :q!,不存在退不出去这回事。权限报错先看自己是谁、在哪个组,别用 777 糊。服务莫名起不来,先 df -h 看一眼。kill -9 留到最后。
回头看,这些命令其实不用背。用得多了会自然形成一个习惯:动手之前先确认自己在哪个目录、改的东西归谁、万一改坏了从哪儿退回去。剩下的查一下就能用。
另外别只在虚拟机里看教程,找件真事做:装个环境、起个小服务、配一个每天备份的任务。命令是用的时候记住的,坑是踩过才记住的。
查手册:https://manpages.ubuntu.com/
写 cron 表达式的时候我会对着这个看:https://crontab.guru/
网硕互联帮助中心






评论前必须登录!
注册