Linux命令拾遗-常用的辅助开发类命令

原创:打码日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处。

简介

之前介绍了大量的命令,有基础操作相关的,也有问题诊断相关的,但Linux中还有一类命令,被时常使用在工作当中,如curl、mysql、ssh、vim等,本篇对它们做一个整体介绍。

使用curl调试接口

curl是一个多功能的网络客户端命令,可以支持非常多的网络协议,如HTTP、FTP、IMAP、SMTP、SMB、LADP、MQTT等,但大部分情况下,我们将其作为HTTP协议的客户端工具来使用,用来调试HTTP接口,常见用法如下:

# 发送HTTP请求,默认GET方法
curl 'http://localhost/user/get'

# -d指定请求体,有-d参数后,curl会使用POST方法
# 如果不指定Content-Type,默认是application/x-www-form-urlencoded
curl 'http://localhost/user/add' -d 'id=32&name=zhangsan'
# --data-urlencode,将请求体做urlencode编码后再发送
curl 'http://localhost/user/add' --data-urlencode 'id=32&name=zhangsan'

# 用-H添加请求头,如下指定Content-Type是application/json
curl 'http://localhost/user/add' -H 'Content-Type: application/json; charset=UTF-8' -d '{"id":32,"name":"zhangsan"}'

# 使用-X,可以指定请求方法
curl -X DELETE 'http://localhost/user/delete'
curl -X PUT 'http://localhost/user/modify' -d 'id=32&name=zhangsan'



# -G,可以将请求体拼接到url,所以下面两种调用方法是等效的
curl -G 'http://localhost/user/add' -d 'id=32&name=zhangsan'
curl 'http://localhost/user/add?id=32&name=zhangsan'

# -i和-I可以显示响应头,区别是-i会同时显示响应头与内容,-I只显示响应头
curl -i 'http://localhost/user/add?id=32&name=zhangsan'

# 查看curl处理细节(非常常用)
curl -v http://www.baidu.com
# -s不显示进度提示信息与错误信息,-S显示错误信息
curl -sS http://www.baidu.com

# 使用time执行curl,只能看到请求整体响应时间
$ time curl "http://www.baidu.com" -o /dev/null -s
...
real    0m0.066s
user    0m0.010s
sys     0m0.000s
# 如下,通过-w可以打印请求详细耗时情况,包括dns查找耗时,连接建立耗时、收到服务端响应的首字节耗时、响应结果全部获取到的耗时,注意时间都是累加的,即相对于命令执行那一刻开始
$ curl -w " time_namelookup:%{time_namelookup}s\n time_connect:%{time_connect}s\n time_starttransfer:%{time_starttransfer}s\n time_total:%{time_total}s\n speed_download:%{speed_download}\n http_code:%{http_code}" "http://www.baidu.com" -o /dev/null -s
 time_namelookup:0.009906s
 time_connect:0.035826s
 time_starttransfer:0.062370s
 time_total:0.062406s
 speed_download:38403.000
 http_code:200
复制代码

另外,curl也可以用来做文件上传与下载,如下:

# 下载文件,-L让curl支持重定向,-#显示进度条,-O响应体下载为文件
curl -LO -# http://localhost/user/avatar/xxxxx.png  
# wget也经常用于下载文件
wget http://localhost/user/avatar/xxxxx.png  

# 上传文件,-F类似于html里的form,使用-F后,Content-Type默认是multipart/form-data,这正是web上常见的文件上传方式  
curl http://localhost/user/avatar/upload -F 'id=32' -F 'avatar=@./xxxxx.png'

# 上传文件,这也是一种上传文件的方式,请求体直接就是文件内容,整个传给服务器
curl http://localhost/user/avatar?id=32 --data-binary '@./xxxxx.png' -#


# curl也可以访问ftp服务器,如下:
# 下载ftp文件
curl -u 用户名:密码 ftp://localhost/user/avatar/xxxxx.png -O

# 上传文件到ftp
curl -u 用户名:密码 ftp://localhost/user/avatar/ -T ./xxxxx.png
复制代码

另外,有时使用curl会出现一些莫名其妙的麻烦,这里分享一下我遇到的几种,大家留个眼熟:

# 一些网站https证书过期了,curl报curl: (60) SSL certificate problem: unable to get local issuer certificate
# 可以用-k忽略https证书校验
curl -k https://www.ywnds.com/

# 一些网站网速极慢,导致curl会阻塞很久,需要指定下网络超时时间
curl --connect-timeout 2 --max-time 2 http://www.baidu.com

# 一些网站会使用gzip压缩响应内容,这会导致curl报Warning: Binary output can mess up your terminal. Use "--output -" to tell
# 使用--compressed即可,使用gzip -d也可以
curl -H 'Accept-Encoding:gzip' http://www.baidu.com/ --compressed
curl -H 'Accept-Encoding:gzip' http://www.baidu.com/ | gzip -d

# 一些网站任然在使用GBK编码,这会导致curl结果乱码,甚至直接报Failed writing body错误,这时需要使用iconv转换一下编码
curl -i http://www.xxxxx.com | iconv -f GBK
# 有时,你想在输出响应结果后再输出一个换行,避免多次curl的结果混在一行上
curl -w '\n' http://localhost/health
复制代码

可以发现,curl几乎可以定义HTTP请求的方方面面,因此,我经常使用curl作为与同事间沟通接口细节的工具,我也看到过不少厂商的api文档,直接使用curl来定义,毕竟对于开发者来说,任何文档都没有代码解释得清楚。

使用mysql命令执行SQL

mysql命令使用起来比较简单,如下:

mysql -h localhost -P 3306 -u root -psecret test_db
复制代码

执行上面命令后,就会进入SQL交互界面,然后你就可以执行SQL语句了,注意指定密码的方式,-psecret之间不能有空格。

其它比较有用的选项如下:

选项 作用
-A 不加载表名、列名等元数据,网络不好时可加快命令启动速度,代价是按Tab键无法自动补齐表名与列名了
--default-character-set utf8mb4 指定字符集,避免某些环境下的乱码
-e 指定要执行的SQL,执行完后直接退出,不进入命令交互界面
-N 查询结果中不展示列名
-t 查询结果以表格形式输出
-B 查询结果不以表格形式输出,字段以tab分隔
-X 查询结果以XML形式输出
-U 安全地执行查询与更新,比如你操作大表时忘记了加limit这种
--pager 指定结果分页展示器,默认是标准输出,--pager=less表示使用less作为分页展示器

这里面比较有意思的是pagerpager可以设置成任何linux命令,来处理查询结果,如下:

$ mysql -h localhost -P 3306 -u root -psecret test_db
# 未设置pager的情况,查询结果直接输出
mysql> select * from app_log where create_time >= '2021-04-18' and create_time < '2021-04-18 17:35:00';
+-------+------------------------------------+---------------------+---------------------+-------+----------+
| id    | log_info                           | create_time         | update_time         | seq   | add_time |
+-------+------------------------------------+---------------------+---------------------+-------+----------+
|  7706 | DOwhV4Odbuf0wVwyZxrJFbBOEGF0fhf7Ab | 2021-04-18 17:22:48 | 2022-03-11 00:25:49 |  7706 |        0 |
|  8155 | abc                                | 2021-04-18 16:55:42 | 2022-07-18 21:28:29 |  8155 |        0 |
| 14535 | uAXFeCJ3jtxhiQJS26q43MarWL5M       | 2021-04-18 17:06:54 | 2022-06-26 21:19:42 | 14535 |        0 |
| 15303 | abc                                | 2021-04-18 17:30:18 | 2022-05-04 00:38:15 | 15303 |        0 |
| 31933 | cLfKXMYkaIta16kzmyWKFC             | 2021-04-18 17:06:19 | 2022-09-14 20:14:10 | 31933 |        0 |
| 32503 | Rb6yMJ6fvViF28YWN9GA               | 2021-04-18 17:33:59 | 2022-03-14 17:38:04 | 32503 |        0 |
+-------+------------------------------------+---------------------+---------------------+-------+----------+
6 rows in set (0.29 sec)

# 设置pager为cat -n,为输出内容添加行号
mysql> pager cat -n
PAGER set to 'cat -n'
mysql> select * from app_log where create_time >= '2021-04-18' and create_time < '2021-04-18 17:35:00';
     1  +-------+------------------------------------+---------------------+---------------------+-------+----------+
     2  | id    | log_info                           | create_time         | update_time         | seq   | add_time |
     3  +-------+------------------------------------+---------------------+---------------------+-------+----------+
     4  |  7706 | DOwhV4Odbuf0wVwyZxrJFbBOEGF0fhf7Ab | 2021-04-18 17:22:48 | 2022-03-11 00:25:49 |  7706 |        0 |
     5  |  8155 | abc                                | 2021-04-18 16:55:42 | 2022-07-18 21:28:29 |  8155 |        0 |
     6  | 14535 | uAXFeCJ3jtxhiQJS26q43MarWL5M       | 2021-04-18 17:06:54 | 2022-06-26 21:19:42 | 14535 |        0 |
     7  | 15303 | abc                                | 2021-04-18 17:30:18 | 2022-05-04 00:38:15 | 15303 |        0 |
     8  | 31933 | cLfKXMYkaIta16kzmyWKFC             | 2021-04-18 17:06:19 | 2022-09-14 20:14:10 | 31933 |        0 |
     9  | 32503 | Rb6yMJ6fvViF28YWN9GA               | 2021-04-18 17:33:59 | 2022-03-14 17:38:04 | 32503 |        0 |
    10  +-------+------------------------------------+---------------------+---------------------+-------+----------+
6 rows in set (0.29 sec)

# 设置pager为grep abc,只查看包含abc的行
mysql> pager grep abc
PAGER set to 'grep abc'
mysql> select * from app_log where create_time >= '2021-04-18' and create_time < '2021-04-18 17:35:00';
|  8155 | abc                                | 2021-04-18 16:55:42 | 2022-07-18 21:28:29 |  8155 |        0 |
| 15303 | abc                                | 2021-04-18 17:30:18 | 2022-05-04 00:38:15 | 15303 |        0 |
6 rows in set (0.29 sec)

# 设置pager为less分页器,这样可以在查询结果中翻页与搜索了
mysql> pager less -iSX
PAGER set to 'less -iSX'
mysql> select * from app_log where create_time >= '2021-04-18' and create_time < '2021-04-18 17:35:00';
+-------+------------------------------------+---------------------+---------------------+-------+----------+
| id    | log_info                           | create_time         | update_time         | seq   | add_time |
+-------+------------------------------------+---------------------+---------------------+-------+----------+
|  7706 | DOwhV4Odbuf0wVwyZxrJFbBOEGF0fhf7Ab | 2021-04-18 17:22:48 | 2022-03-11 00:25:49 |  7706 |        0 |
|  8155 | abc                                | 2021-04-18 16:55:42 | 2022-07-18 21:28:29 |  8155 |        0 |
| 14535 | uAXFeCJ3jtxhiQJS26q43MarWL5M       | 2021-04-18 17:06:54 | 2022-06-26 21:19:42 | 14535 |        0 |
| 15303 | abc                                | 2021-04-18 17:30:18 | 2022-05-04 00:38:15 | 15303 |        0 |
| 31933 | cLfKXMYkaIta16kzmyWKFC             | 2021-04-18 17:06:19 | 2022-09-14 20:14:10 | 31933 |        0 |
| 32503 | Rb6yMJ6fvViF28YWN9GA               | 2021-04-18 17:33:59 | 2022-03-14 17:38:04 | 32503 |        0 |
+-------+------------------------------------+---------------------+---------------------+-------+----------+
(END)

# 设置pager为md5sum -,这样可以为查询结果生成md5
# 对比md5就能知道当前时间段数据是否产生了变化
mysql> pager md5sum -
PAGER set to 'md5sum -'
mysql> select * from app_log where create_time >= '2021-04-18' and create_time < '2021-04-18 17:35:00';
40ed2c49a72ff68ba11b97d843bb4da2  -
6 rows in set (0.29 sec)

mysql> select * from app_log where create_time >= '2021-04-18' and create_time < '2021-04-18 17:35:00';
40ed2c49a72ff68ba11b97d843bb4da2  -
6 rows in set (0.31 sec)

# 先使用cat将第一次查询结果保存到文件中,然后使用icdiff对比查询结果是否变化
mysql> pager cat > result.txt
PAGER set to 'cat > result.txt'
mysql> select * from app_log where create_time >= '2021-04-18' and create_time < '2021-04-18 17:35:00';
6 rows in set (0.31 sec)

mysql> pager icdiff result.txt /dev/stdin
PAGER set to 'icdiff result.txt /dev/stdin'
mysql> select * from app_log where create_time >= '2021-04-18' and create_time < '2021-04-18 17:35:00';
复制代码

pager_icdiff
如果要恢复pager的话,只需要输入nopager并回车即可。

扫描二维码关注公众号,回复: 13674730 查看本文章

另外,对于mysql的相关命令行选项,是可以永久配置在mysql.cnf配置文件中的,这样可以避免每次都要在命令行带上自己常用的选项,如下:

$ sudo vim /etc/mysql/conf.d/mysql.cnf
[mysql]
default-character-set=utf8mb4
pager=less -iSFX
safe-updates=TRUE
复制代码

使用ssh管理主机

登录远程主机

一般我们使用ssh来登录并管理远程主机,比如安装软件、排查问题等,常见用法如下:

# 登录到主机192.168.0.1上,使用work用户,然后输入work用户密码即可
$ ssh [email protected]

# -p指定端口,有时主机为了安全会不使用默认的22端口
$ ssh [email protected] -p 8022

# 直接在远程主机上执行命令
$ ssh [email protected] -e 'ping www.baidu.com'
PING www.a.shifen.com (112.80.248.76) 56(84) bytes of data.
64 bytes from 112.80.248.76 (112.80.248.76): icmp_seq=1 ttl=54 time=19.1 ms
64 bytes from 112.80.248.76 (112.80.248.76): icmp_seq=2 ttl=54 time=19.9 ms 
复制代码

上传下载文件

除了远程登录到主机上,我们经常需要上传下载文件,如下:

# scp和ssh是一个软件包的,为上传下载场景定制的命令,用法如下:
# 下载192.168.0.1主机上/home/work/logs/app.log到本机的logs目录下
$ scp [email protected]:/home/work/logs/app.log ./logs/

# 上传本机./logs/app.log文件到192.168.0.1主机上/home/work/logs/目录里
$ scp ./logs/app.log [email protected]:/home/work/logs/

# 实际上scp的源文件与目标文件都可以是远程主机上的,如下:
$ scp [email protected]:/home/work/logs/app.log [email protected]:/home/work/logs/app.log


# 实际上使用ssh也能上传下载
# 使用ssh下载,其中pv命令是为了查看进度,换成cat其实也可以
$ ssh [email protected] 'cat /home/work/logs/app.log' | pv > ./logs/app.log

# 使用ssh上传,其中pv命令是为了查看进度,换成cat其实也可以
$ pv ./logs/app.log | ssh [email protected] 'cat > /home/work/logs/app.log'

# 对比远程文件与本地文件内容
$ ssh [email protected] 'cat /path/to/remotefile' | icdiff /path/to/localfile –
复制代码

sshfs挂载远程目录

如果你觉得这样上传下载好麻烦,可以使用sshfs将远程主机上的目录,直接挂载到本机上,这样你就可以像访问本机文件一样访问远程文件了。

sshfs是基于fuse机制与ssh协议实现的用户态文件系统,只要是你能用ssh的地方都能用sshfs,并且由于是用户态的文件系统,因此它并不像NFS那样需要特殊权限,只要网络连通即可,使用方法如下:

# sshfs挂载目录
$ sshfs [email protected]:/home/work/logs /home/work/logs

# 列出文件
$ ls /home/work/logs
app_2022-01-23T12:05:51.log  app_2022-01-23T12:05:53.log  app_2022-01-23T12:05:57.log  app_2022-01-23T12:06:00.log

# 使用ssh列出远程目录,与上面结果是一样的
$ ssh [email protected] 'ls /home/work/logs'
app_2022-01-23T12:05:51.log
app_2022-01-23T12:05:53.log
app_2022-01-23T12:05:57.log
app_2022-01-23T12:06:00.log

复制代码

也许你会奇怪,为啥上面结果一个没换行而另一个换行了,这是因为ls会检测输出对象是否是终端,如果是终端就会横排展示,否则竖排展示,不信你可以ls | cat看看。

其实好多命令都会有这种行为,比如curl默认不显示进度,但如果输出对象不是终端,如curl|cat,就会显示出进度信息。

免密码登录

一旦你这样用着ssh,就会发现每次都需要输入密码好麻烦,好在ssh提供了私钥认证机制,因此我们可以生成一对公私钥来避免每次都要输入密码,如下:

# 使用ssh-keygen生成ssh密钥对,使用rsa算法,长度4096,生成的密钥默认~/.ssh目录下,私钥叫id_ras,公钥叫id_ras.pub
ssh-keygen -o -t rsa -b 4096 -C "[email protected]"

# 使用ssh-copy-id将公钥上传到目标主机上
ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]
# 没有ssh-copy-id时,这样上传公钥也是可以的
cat ~/.ssh/id_rsa.pub | ssh [email protected] 'cat >> ~/.ssh/authorized_keys'

# 测试公钥是否生效,如果看到Authentication succeeded (publickey).字样,说明成功
ssh -vT [email protected] </dev/null
复制代码

是的,相信不少用过github/gitee/gitlab的同学会感觉到熟悉,其实github等也是一样使用ssh密钥来避免git操作需要输入密码的,配置过程是类似的:

  1. 使用ssh-kengen生成密钥对。
  2. 将公钥手动拷贝到github的ssh密钥管理页面上并保存。
  3. 测试配置成功。

端口转发

有时,两个主机A、C之间网络并不互通,但A和B互通,B和C互通,这种情况下,我们可以利用B主机做一个端口转发,使得主机A可以访问主机C上的网络服务。

能够实现端口转发的软件有很多,如iptables、socat、portmap、rinetd等,而ssh也是常见的一个,用法如下:

# ssh本地端口转发,在A机器上执行,会在A机开启2001端口,并将此端口数据发到B机,B机又转发到C机的80端口
ssh -fgN -L2001:host_c:80 work@host_b
# ssh远端端口转发,在B机器上执行,在A机开启22333端口(由A机sshd服务打开),将A机22333端口流量通过B机(中转机)转到C机的80端口上
ssh -fgN -R 22333:host_c:80 work@host_a

# ssh远端动态端口转发,在B机器上执行,会在A机开启2222端口开放socks代理服务,被代理的数据会发到B机,B机又转发到任何B机能访问的网络服务上
ssh -fgN -R 2222 work@host_a
# ssh本地动态端口转发,在A机器上执行,会在A机开启2222端口开放socks代理服务,被代理的数据会发到B机,B机又转发到任何B机能访问的网络服务上
ssh -Nfg -D 2222 work@host_b

# A机通过本机socks代理,登录到C机
ssh -o ProxyCommand='ncat --proxy 127.0.0.1:2222 --proxy-type socks5 %h %p' work@host_c
# A机通过B机ssh登录C机,其实就是两次ssh登录过程
ssh -t work@host_b 'ssh work@host_c'
复制代码

为啥会有本地端口转发与远端端口转发两种转发方式呢?

这和允许网络连接的方向有关,比如有些情况下,B能连接到A,但A不能连接到B,这时就需要使用远端端口转发了!

总结

除了这些常用的命令外,Linux中还有很多其它类型的工具命令,比如:

  • vim、emacs:用来编辑文本文件,实际上你也可以把他们配置成类似idea的IDE,感兴趣可参考spacevim、spacemacs。
  • openssl:用来生成密钥文件、证书文件以及做加密、解密等操作。
  • ffmpeg:可以处理音视频文件,如mp4转flv、mp4转gif、录屏、剪裁、观看直播等。
  • convert:可以进行图片格式转换,如png转jpeg。
  • jp2a:可以将图片变成字符画。
  • wkhtmltopdf、xhtml2pdf可以将html转换为pdf,pandoc可以进行各种文档的格式转换。

这里就不一一介绍了,后面有机会可以单独拿出来介绍介绍。

本系列文章索引
Linux命令拾遗-入门篇
Linux命令拾遗-文本处理篇
Linux命令拾遗-软件资源观测
Linux命令拾遗-硬件资源观测
Linux命令拾遗-剖析工具
Linux命令拾遗-动态追踪工具
Linux命令拾遗-理解系统负载
Linux命令拾遗-top中的%nice是啥
Linux命令拾遗-网络抓包工具
Linux命令拾遗-查看系统信息

往期内容

Linux命令拾遗-入门篇
原来awk真是神器啊
Linux文本命令技巧(上)
Linux文本命令技巧(下)
字符编码解惑

猜你喜欢

转载自juejin.im/post/7056317003392352264
今日推荐