引 入
linux是一个庞大复杂的系统。整天跟它打交道的运维或开发人员难免不遇到什么问题。这里,本人聊聊遇到的一个跟scp相关的奇葩问题。
一、问题描述
两台centos6.7主机(主机一:172.16.13.62和主机二:172.16.13.72),都安装好ssh,相关的ssh连接配置也没问题,但是在用scp进行两主机之间的文件传输复制时,出现以下情况:
在主机一上操作scp,成功从主机二传输文件到主机一。当然也能成功把文件从主机一成功传输到主机二。如:
[[email protected] ~]#scp 172.16.13.72:/root/20160215.log /root [email protected]‘s password: 20160215.log 100% 3434 3.4KB/s 00:00 [[email protected] ~]#
而在主机二上操作scp,做从主机一传输文件到主机二时,成功输入密码后,出现如下情况:
[[email protected] ~]#scp 172.16.13.62:/root/20160215.log /root [email protected]‘s password: ---------change alias here----------- [[email protected] ~]#
打印了一句"change alias here",然后就结束了,scp没有成功传输文件。当然从主机二传输文件到主机一的时候,依旧也是打印一句"change alias here",传输也是没有成功的。
为什么在主机一上操作scp成功,而在主机二上操作却不成功呢?那句"change alias here"又是从哪里来的呢?我做出了以下分析:
二、分析解决
以下分析中,主机二也叫错误主机,主机一成为正确主机。
步骤:
1) 通过scp -v查看错误主机的debug详细信息
[[email protected] ~]#scp -v 172.16.13.62:/root/20160215.log /root
从debug中可以看出这次scp的运行的结果状态是有错误的,但是不容易发现错误点在哪,所以我在正确主机上也debug来对比分析。
2) 对比正确主机分析错误
[[email protected] ~]#scp -v 172.16.13.72:/root/20160215.log /root
从debug中可以看出这次scp的运行的结果状态是有正确的。对比过后分析后可以大概把错误点定位在"Send file modes 跟Sink"这两个入口。
3) 分析出现"change alias here"的地方
由于发现"change alias here"是在非交互式登录时就会出现,故很快可以找出"change alias here"的所在地。即:~/.bashrc
发现原来是前面为了标识一下可以在~/.bashrc中定义命令别名而加上的一句echo回显打印。把相关的echo删除后可以发现scp可以正常操作,问题解决。
4) 回头分析错误出现深一步原因
多一个echo就会出现scp错误?通过查阅各种相关资料得知,基于ssh的scp命令的工作模式主要有source mode跟sink mode两种,建立连接后。
如果请求方接收到的第一个字符不是大写字符"C",如上面例子的"---------change alias here-----------"。则会由于这远端shell的配置文件输出“加入”的协议会话而退出了scp。
如果请求方接收到的第一个字符是大写字符"C",如"C0644 3334 20160215.log",你就会发现一个有趣的情况,scp程序将会成功读取3334个字节,20160215.log文件剩下的字节将会在屏幕显示出来。
[[email protected] ~]# scp 172.16.13.62:20160215.log . [email protected]‘s password: 20160215.log 100% 3334 3.3KB/s 00:00 6/index.php" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36" [[email protected] ~]#
而读取到的20160215.log文件里面,会包含“C0644 3334 20160215.log”这句echo打印的话。
是不是挺有意思呢?
由于问题已经解决,自己又没很大决心再往细细去研究这SCP的工作原理,所以我的分析就到此为止了。想深入了解SCP原理的朋友可以参考How the SCP protocol works这篇文件,写得还不错。
三、补充:bash的配置文件类型
主要可以分为两类:
profile类:为交互式登录的shell进程提供配置
bashrc类:为非交互式登录的shell进程提供配置
全局:对所有用户都生效 | 用户个人:仅对当前用户有效 | 功用 | |
profile类 |
/etc/profile 或 /etc/profile.d/*.sh |
~/.bash_profile |
1、定义环境变量; 2、运行命令或脚本 |
bashrc类 | /etc/bashrc | ~/.bashrc |
1、定义本地变量; 2、定义命令别名; |
登录类型:
交互式登录shell进程:
直接通过某终端输入账号和密码后登录打开的shell进程;
使用su命令:su - USERNAME, 或者使用 su -l USERNAME执行的登录切换;
非交互式登录shell进程:
su USERNAME执行的登录切换;
图形界面下打开的终端;
运行脚本
配置文件读取顺序:
交互式登录shell进程:
/etc/profile --> /etc/profile.d/* --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc
非交互式登录shell进程:
~/.bashrc --> /etc/bashrc --> /etc/profile.d/*
结 语
发现问题不可怕,解决问题时,分析思路最重要。
如果朋友你自己也有linux相关的奇葩问题,不要一个人留着哦,期待与您一起讨论分享。
附:如对上面描述有疑问,期待与朋友您共同探讨。本人QQ:1084569767