阅读 83

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

简介

之前介绍了大量的命令,有基础操作相关的,也有问题诊断相关的,但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并回车即可。

另外,对于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 work@192.168.0.1 # -p指定端口,有时主机为了安全会不使用默认的22端口 $ ssh work@192.168.0.1 -p 8022 # 直接在远程主机上执行命令 $ ssh work@192.168.0.1 -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 work@192.168.0.1:/home/work/logs/app.log ./logs/ # 上传本机./logs/app.log文件到192.168.0.1主机上/home/work/logs/目录里 $ scp ./logs/app.log work@192.168.0.1:/home/work/logs/ # 实际上scp的源文件与目标文件都可以是远程主机上的,如下: $ scp work@192.168.0.1:/home/work/logs/app.log work@192.168.0.2:/home/work/logs/app.log # 实际上使用ssh也能上传下载 # 使用ssh下载,其中pv命令是为了查看进度,换成cat其实也可以 $ ssh work@192.168.0.1 'cat /home/work/logs/app.log' | pv > ./logs/app.log # 使用ssh上传,其中pv命令是为了查看进度,换成cat其实也可以 $ pv ./logs/app.log | ssh work@192.168.0.1 'cat > /home/work/logs/app.log' # 对比远程文件与本地文件内容 $ ssh work@192.168.0.1 'cat /path/to/remotefile' | icdiff /path/to/localfile – 复制代码

sshfs挂载远程目录

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

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

# sshfs挂载目录 $ sshfs work@192.168.0.1:/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 work@192.168.0.1 '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 "zhangsan@example.com" # 使用ssh-copy-id将公钥上传到目标主机上 ssh-copy-id -i ~/.ssh/id_rsa.pub work@192.168.0.1 # 没有ssh-copy-id时,这样上传公钥也是可以的 cat ~/.ssh/id_rsa.pub | ssh work@192.168.0.1 'cat >> ~/.ssh/authorized_keys' # 测试公钥是否生效,如果看到Authentication succeeded (publickey).字样,说明成功 ssh -vT work@192.168.0.1 </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可以进行各种文档的格式转换。

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


作者:打码日记
链接:https://juejin.cn/post/7056317003392352264


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 gxwowoo@163.com 举报,一经查实,本站将立刻删除。
相关推荐