聊一聊shell中字符串 单引号 双引号以及执行字符串命令中的坑

shell 同时被 2 个专栏收录
5 篇文章 0 订阅
8 篇文章 0 订阅

一直以来对shell中字符串的了解就是单引号和双引号内的都是字符串,双引号内字符串可以被替换成变量,单引号就是原字符串输出,今天在开发一个hdfs跨集群拷贝数据脚本时候发现shell echo出来同样的命令手动执行可以执行,在shell内通过${cmd}方式却报错,通过sh -x a.sh才发现问题产生的根源,具体如下:

众所周知hdfs在集群内部拷贝文件命令如下:

hdfs dfs -cp src_path target_path

我这里是跨集群拷贝,集群的配置文件中集群部门的同事由于种种原因不愿意配置别的集群的nameservice,我要实现最简单的方式就是通过-D将这些参数传进去,完整命令如下:

hdfs dfs -Ddfs.nameservices='ns1,ns2' -Ddfs.ha.namenodes.ns2='nn1,nn2' -Ddfs.namenode.rpc-address.ns2.nn1='master01:8888' -Ddfs.namenode.rpc-address.ns2.nn2='master02:8888' -Ddfs.client.failover.proxy.provider.ns2='org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider' -cp src_path hdfs://ns2/target_path

上述命令中ns1是我们部门集群,ns2是别的部门的集群,需要将我们部门的数据拷贝到别的集群,上述命令手动执行是不会有任何问题的,在shell中使用时候我是这么使用的,部分片段如下:

hdfs_conf="-Ddfs.nameservices='ns1,ns2' -Ddfs.ha.namenodes.ns2='nn1,nn2' -Ddfs.namenode.rpc-address.ns2.nn1='master01:8888' -Ddfs.namenode.rpc-address.ns2.nn2='master02:8888' -Ddfs.client.failover.proxy.provider.ns2='org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider'"
cp_cmd="hdfs dfs ${hdfs_conf} -cp src_path hdfs://ns2/target_path"
# 输出一下命令
echo ${cp_cmd}
# 执行命令
${cp_cmd}

输出信息如下:

hdfs dfs -Ddfs.nameservices='ns1,ns2' -Ddfs.ha.namenodes.ns2='nn1,nn2' -Ddfs.namenode.rpc-address.ns2.nn1='ns1:8888' -Ddfs.namenode.rpc-address.ns2.nn2='ns2:8888' -Ddfs.client.failover.proxy.provider.ns2='org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider' -cp src_path hdfs://ns2/target_path
cp: Couldn't create proxy provider null

看echo出来的命令是没有任何问题的,但是却提示provider为null,导致执行失败,添加-x参数以后输出如下:

+ hdfs_conf='-Ddfs.nameservices='\''ns1,ns2'\'' -Ddfs.ha.namenodes.ns2='\''nn1,nn2'\'' -Ddfs.namenode.rpc-address.ns2.nn1='\''ns1:8888'\'' -Ddfs.namenode.rpc-address.ns2.nn2='\''ns2:8888'\'' -Ddfs.client.failover.proxy.provider.ns2='\''org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider'\'''
+ cp_cmd='hdfs dfs -Ddfs.nameservices='\''ns1,ns2'\'' -Ddfs.ha.namenodes.ns2='\''nn1,nn2'\'' -Ddfs.namenode.rpc-address.ns2.nn1='\''ns1:8888'\'' -Ddfs.namenode.rpc-address.ns2.nn2='\''ns2:8888'\'' -Ddfs.client.failover.proxy.provider.ns2='\''org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider'\'' -cp src_path hdfs://ns2/target_path'
+ echo hdfs dfs '-Ddfs.nameservices='\''ns1,ns2'\''' '-Ddfs.ha.namenodes.ns2='\''nn1,nn2'\''' '-Ddfs.namenode.rpc-address.ns2.nn1='\''ns1:8888'\''' '-Ddfs.namenode.rpc-address.ns2.nn2='\''ns2:8888'\''' '-Ddfs.client.failover.proxy.provider.ns2='\''org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider'\''' -cp src_path hdfs://ns2/target_path
hdfs dfs -Ddfs.nameservices='ns1,ns2' -Ddfs.ha.namenodes.ns2='nn1,nn2' -Ddfs.namenode.rpc-address.ns2.nn1='ns1:8888' -Ddfs.namenode.rpc-address.ns2.nn2='ns2:8888' -Ddfs.client.failover.proxy.provider.ns2='org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider' -cp src_path hdfs://ns2/target_path
+ hdfs dfs '-Ddfs.nameservices='\''ns1,ns2'\''' '-Ddfs.ha.namenodes.ns2='\''nn1,nn2'\''' '-Ddfs.namenode.rpc-address.ns2.nn1='\''ns1:8888'\''' '-Ddfs.namenode.rpc-address.ns2.nn2='\''ns2:8888'\''' '-Ddfs.client.failover.proxy.provider.ns2='\''org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider'\''' -cp src_path hdfs://ns2/target_path
cp: Couldn't create proxy provider null

相比到这里各位应该看明白了,虽然echo输出来的命令是正确的,但是在执行过程中,shell会给程序添加单引号,结果单引号就很多了,其中有转义,导致最终真实执行的命令很乱。

此时如果要执行这个命令,可以把最后的${cp_cmd}修改为eval ${cp_cmd},eval会把中间的单引号和双引号全部去掉,此时执行就是我想要的结果,感兴趣的朋友可以试着自己debug试试。

  • 0
    点赞
  • 1
    评论
  • 1
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

catcher92

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值