基础概要
一些Linux的基础操作已经在我以前写的Linux基础概要一书中有阐述,本篇文章只列出和服务器相关的常用操作。
关于远程连接
Ubuntu Server自14.04版本以后默认禁止root远程登录,但是阿里云等镜像会定制这个配置,允许root远程登录。如果需要开启root ssh的话,修改/etc/ssh/sshd_config
配置文件重启ssh即可。相关的配置已经在之前的文章提到过: https://www.jianshu.com/p/967e3a04a6c7
软件管理
我维护服务器的原则是各种手段杜绝直接编译安装,以包管理部署为尊。因此能不编译的都不编译,我采用的部署优先级如下:
- 软件开发商的官方仓库(比如nginx、postgresql、docker等)
- 软件开发商的PPA仓库(基本等同于软件开发商官方仓库对待,如timescaledb, ansible等等)
- Ubuntu官方仓库(如Apache, OpenJDK, tomcat等等)
- 社区维护方的PPA仓库(如redis, oracle-java等)
- 官方直接release的二进制包+其他第三方的部署脚本
- 编译安装
原则上,软件开发方有官方仓库或者官方PPA仓库的,优先考虑,因为可选版本较多,漏洞修补更加及时,并且契合官方文档。Ubuntu官方仓库相对版本较低,但是通常稳定性较好,安装部署也比较方便,如无必要追新也可以考虑。没有软件仓库部署的情况下,也应该优先考虑使用官方或社区方编译好的release版本。最后都没有再考虑自行编译安装。编译环境也可以在本机搭建(同版本的Ubuntu),编译好以后打包编译好的二进制包上传到服务器上部署。
对于软件仓库的管理,我的规则是:
- Ubuntu官方仓库配置在
/etc/apt/sources.list
- 对于非Ubuntu官方仓库,统一放在
/etc/apt/sources.list.d/xxx.list
(ppa也是这个规范)
关于apt
的详细操作手册可以参见Ubuntu官方文档。以下列出最常用的一些操作。
安装软件
sudo apt update
# 从仓库中安装指定软件包
sudo apt install [-y] package1 [package2 ...]
# 从仓库中安装指定版本的软件包
sudo apt install [-y] package=version
# 从本地的deb文件中直接安装,相对路径绝对路径都支持
sudo apt install [-y] /path/to/deb
注意Ubuntu安装软件包的时候不会主动刷新本地缓存,因此安装/升级软件包的时候先apt update
。sudo
只是表示这个命令必须使用root
权限,如果当前已经是root
,可以不加,以下不再赘述。
升级软件
# 升级指定软件包(命令同安装指定软件包命令)
sudo apt install [-y] package1 [package2 ...]
# 升级所有可升级的软件包
sudo apt full-upgrade [-y]
降级软件
sudo apt install [-y] package=version
卸载软件
sudo apt purge/remove package
注意:
purge
和remove
的区别。remove
只卸载软件包的主体内容(比如/usr/lib/
下的相关内容),而purge
是更彻底的删除,除了删除主体内容之外,还会连带删除配置文件(/etc
)、数据文件(/var/lib/
)等。因此如果卸载数据库的话,需要考虑清楚是否数据库目录不再需要。
自动卸载不被依赖的软件包
软件包安装的时候会附带安装被依赖的软件包,这些依赖的软件包被标记为autoinstall
状态。当别的软件包被删除或者升级之后,这些软件包可能不再被依赖。apt命令行会给出提示。可以使用以下命令快速删除这些不再依赖的软件包:
## --purge参数的含义如同上面的purge操作
sudo apt autoremove [--purge]
注意: 当软件包被标记为
hold
的时候,是不会被autoremove
清除掉的。
固定软件版本
如果需要固定软件版本,不受full-upgrade
/upgrade
/autoremove
的影响,可以冻结版本:
# package可用正则
sudo apt-mark hold package
# 解除冻结版本(同样支持正则)
sudo apt-mark unhold package
# 列出当前处于autoinstall/manual/hold状态的包
sudo apt-mark showauto/showmanual/showhold
注意: 冻结版本只是限制了自动升级、自动卸载等功能不会影响到
hold
/manual
状态的软件包,但是不受apt install
的影响,如果需要手工升级某些被冻结的软件包,一样可以使用apt install
命令直接升级。manual
状态代表该软件包手动安装,不受autoremove
的影响,但是可以通过upgrade
/full-upgrade
升级。hold
状态代表这个软件包不受autoremove
/upgrade
/full-upgrade
影响。apt install package
安装的package为manual
状态,被package
依赖安装的软件包则为autoinstall
状态。
列出仓库可以安装的软件包版本
apt policy package
# 下面这个更详细,可以列出每个版本依赖的软件包以及包信息等等
apt show -a package
列出已安装的软件包
apt list
dpkg -l
列出安装包释放出哪些文件
dpkg -L package
找出指定文件是哪个软件包释放出来的
dpkg -S /path/to/file # 如dpkg -S `which git`
搜索软件包
apt search <keywords>
列出软件包依赖关系
apt depends <package>
自动更新
对于暴露在互联网的服务器,可能希望自动更新安全补丁,如需启用自动更新,可以参考Ubuntu官方文档详情。
sudo apt install -y unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades
当dpkg-reconfigure
询问是否启用自动更新的时候,选择Yes
便会生成一个/etc/apt/apt.conf.d/20auto-upgrades
配置文件,表示启用自动更新,也可以自定义这个配置文件更改一些行为。
/etc/apt/apt.conf.d/50unattended-upgrades
这个配置文件默认只启用${distro_id}:${distro_codename}
和${distro_id}:${distro_codename}-security
两个仓库,即安全更新,大部分情况是够用的。如果需要更新其他仓库的包直接定制这个文件即可。如果需要启用自动更新之后自动autoremove
,修改Unattended-Upgrade::Remove-Unused-Dependencies "true";
这一项就好了,如果需要自动清理掉多余的内核文件,改这一项: Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
升级操作系统
Ubuntu支持跨版本升级操作系统,通常在下一个版本发布后的第二个迭代(如16.04.1, 18.04.1等)更新升级方案。使用以下命令可以升级到下一个LTS版本:
sudo do-release-upgrade
如果能直接上新的服务器并做迁移的话,是没必要进行这个操作的。如果需要高版本的新特性,并且暂时没有多余资源上新服务的话,只能通过升级操作系统解决。如以下情况:
- 需要启用Nginx的HTTP 2.0协议支持,需要openssl版本在1.0.1e以上版本,需要升级操作系统到16.04以上版本
- 需要OpenJDK 11版本,这个版本在18.04版本以上
- ...
注意: 在升级之前,需要先阅读新版本的Release Notes,确认新版本和当前版本有没有出现废弃软件包,升级不兼容当前配置的情况。如Ubuntu 14.04将Apache更新至2.4版本,而之前一个LTS使用2.2版本,配置文件不兼容,会导致升级之后服务启动失败,需要手改配置。再比如Ubuntu 18.04废弃了Tomcat7这个包,改为了Tomcat8,所以如果旧版本服务器安装了Tomcat7,需要注意迁移war包和配置到Tomact8的目录下,等等。最后就是
/etc/apt/sources.list.d/*.list
中的文件基本都得手改仓库的,可能很多仓库在升级过程中都不会得到正确的仓库配置,所以在升级之前建议手改开发代号或者版本号等参数。在升级之前,强烈建议先在测试环境做升级测试,以评估升级之后的风险等。
服务管理
对于Ubuntu 14.04以及之前的版本,Ubuntu的service manager使用upstart
,从16.04开始改为了Systemd
。目前不考虑老的upstart了,如有需要直接查阅upstart的文档即可。以下内容针对目前Ubuntu的Systemd服务管理常用操作。
Systemd官方文档: https://www.freedesktop.org/wiki/Software/systemd/
启动/停止/重启/看状态
sudo systemctl start/stop/restart/status <service>[.service]
# 以下这个命令兼容老的SysV命令,照顾老运维,在CenOS 7使用会有警告,但是Ubuntu不会
sudo service <service> start/stop/restart/status
开机自启动
sudo systemctl enable <service>[.service]
# 取消开机自启动
sudo systemctl disable <service>[.service]
列出服务
# 列出已知的service name(unit),可以根据state过滤
systemctl list-unit-files [--state=STATE]
# 列出当前处于running状态的服务
systemctl list-units --type=service --state=running
查看日志
日志有两种情况,一种是服务本身运行的时候就会打印的日志文件(比如Java程序使用log4j
/logback
等日志框架直接将日志打印到某个日志文件中),另一种是输出到标准输出,被service manager捕获到的日志。
对于程序本身会打印日志的情况,直接在对应的日志路径查看就可以了。对于Systemd捕获到标准输出/标准错误的日志,是保存为二进制格式的,无法直接通过文本处理命令查看,需要使用journalctl
命令查看。常用的操作如下:
journalctl [-x] [-e] [-f] -u <service>
参数说明:
-
-u
: 指明unit产生的日志,即服务名 -
-x
: 对日志输出加入更多描述信息(catalog) -
-e
: 滚动到最新的日志,通常-xe
连用 -
-f
: 等同于tail -f
的效果 - 其他参数参考man手册
在线监控
- top
- htop (建议在F2配置-Display options-除了Shadow other users' processes之外全勾选)
- atop
- vmstat
- pidstat
- sar
- ...
查看登录状态
last
# 查看bad login
lastb
查看当前登录用户以及正在进行的操作
w
端口监控
ss -nltp
对于看udp端口监听状况把-t
换成-u
即可。-p
参数打印进程pid,这个参数需要sudo
权限,否则显示不出来pid
进程管理
列出进程列表
# 列出所有进程
ps aux
# 按照父子进程关系列出进程
ps exf
pstree -a
给进程发信号
# 给指定的pid发送信号,默认信号为SIGTERM,即signal id为15的信号
kill [-SIGNAL] <pid1> [pid2 ...]
# 批量筛选进程或者批量发送信号
killall/pkill/pgrep