【问题标题】:bash create many directories if it doesn't exist over ssh如果 ssh 不存在,bash 创建许多目录
【发布时间】:2013-02-19 18:08:46
【问题描述】:

我想在远程服务器 2 上创建许多在服务器 1 上已经存在的目录。 我在 server1 上的脚本:

LOG_DIR="/opt/server1/service/logs/"
DEST_HOST="server2"
DEST_USER="logger"
DEST_DIR="/volumes/storage/server1"

LISTEN_DIR=$(find $LOG_DIR -type d | tr '\n' ' ')

ssh $DEST_USER@$DEST_HOST " for Y in $LISTEN_DIR
                do
                    if [ ! -d  $DEST_DIR$Y ]; then
                        mkdir -p $DEST_DIR$Y;
                    fi
                done"

但是在目录 /opt/server1/service/logs/ 中的 server1 上还有其他几个目录... 脚本结果:

[20:00 root@server1:~]# bash -x script.sh
+ LOG_DIR=/opt/server1/service/logs/
+ DEST_HOST=server2
+ DEST_USER=logger
+ DEST_DIR=/volumes/storage/server1
++ find /opt/server1/service/logs/ -type d
++ tr '\n' ' '
+ LISTEN_DIR='/opt/server1/service/logs/ /opt/server1/service/logs/org.service-com.settlement.host.ui-1.0.0.SNAPSHOT /opt/server1/service/logs/com.springsource.server.repository.hosted-2.0.0.RELEASE /opt/server1/service/logs/org.service-com.xml2titp.ws-1.0.0.SNAPSHOT /opt/server1/service/logs/org.service-com.mportal.ws.oracle-1.0.0.SNAPSHOT /opt/server1/service/logs/access /opt/server1/service/logs/com.springsource.server.admin.web-2.0.0.RELEASE /opt/server1/service/logs/org.flex.web.plan-2 /opt/server1/service/logs/org.service-com.admin.host-1.0.0.SNAPSHOT /opt/server1/service/logs/org.service-com.tickets.ws-1.0.0.SNAPSHOT /opt/server1/service/logs/org.service-com.apijson.ws-1.0.0.SNAPSHOT /opt/server1/service/logs/apool_xyz.plan-2 /opt/server1/service/logs/org.service-com.json2titp.host.ui-1.0.0.SNAPSHOT /opt/server1/service/logs/server1 /opt/server1/service/logs/org.service-com.apijson.host.ui-1.0.0.SNAPSHOT /opt/server1/service/logs/org.flex.web.plan-2-org.service-com.flex.bundle.main-1.0.0.SNAPSHOT /opt/server1/service/logs/org.service-com.xyzsettlement.ws-1.0.0.SNAPSHOT /opt/server1/service/logs/org.service-com.host-1.0.0.SNAPSHOT /opt/server1/service/logs/wrapper '
+ ssh logger@server2 'IFS_OLD=  

                for Y in /opt/server1/service/logs/ /opt/server1/service/logs/org.service-com.settlement.host.ui-1.0.0.SNAPSHOT /opt/server1/service/logs/com.springsource.server.repository.hosted-2.0.0.RELEASE /opt/server1/service/logs/org.service-com.xml2titp.ws-1.0.0.SNAPSHOT /opt/server1/service/logs/org.service-com.mportal.ws.oracle-1.0.0.SNAPSHOT /opt/server1/service/logs/access /opt/server1/service/logs/com.springsource.server.admin.web-2.0.0.RELEASE /opt/server1/service/logs/org.flex.web.plan-2 /opt/server1/service/logs/org.service-com.admin.host-1.0.0.SNAPSHOT /opt/server1/service/logs/org.service-com.tickets.ws-1.0.0.SNAPSHOT /opt/server1/service/logs/org.service-com.apijson.ws-1.0.0.SNAPSHOT /opt/server1/service/logs/apool_xyz.plan-2 /opt/server1/service/logs/org.service-com.json2titp.host.ui-1.0.0.SNAPSHOT /opt/server1/service/logs/server1 /opt/server1/service/logs/org.service-com.apijson.host.ui-1.0.0.SNAPSHOT /opt/server1/service/logs/org.flex.web.plan-2-org.service-com.flex.bundle.main-1.0.0.SNAPSHOT /opt/server1/service/logs/org.service-com.xyzsettlement.ws-1.0.0.SNAPSHOT /opt/server1/service/logs/org.service-com.host-1.0.0.SNAPSHOT /opt/server1/service/logs/wrapper  
                do
                    if [ ! -d  /volumes/storage/server1 ]
                    then
                        mkdir -p /volumes/storage/server1;
                    fi;
                done;'

【问题讨论】:

  • 问题是你的 ssh 命令有双引号,$Y 在你执行命令时直接“本地”扩展。

标签: bash ssh directory


【解决方案1】:

尝试这样做:

find local_dir -type d -print0 |
ssh remote 'while IFS="" read -r -d "" a; do mkdir -p "remote_dir/$a"; done'

或者,如果您更喜欢单线:

find local_dir -type d -print0 | ssh remote 'while IFS="" read -r -d "" a; do mkdir -p "remote_dir/$a"; done'

解释

  • find local_dir -type d :从 local_dir 打印所有目录,所以 STDOUT
  • | : Unix pipe : 将最新命令的STDOUT 分支到下一个命令的STDIN
  • ssh remote 'remote_command' :ssh 到远程服务器,并执行命令。需要单个 ' 引号以防止 shell 插入 $a 变量
  • while read a; do mkdir -p remote_dir/$a; done :远程命令,它读取STDIN
  • 使用mkdir -p,无需检查是否存在任何目录

【讨论】:

  • 我不明白这个结构
  • 可能需要添加一个解释'而不是"
  • 这种情况如何组织如何检查目录是否存在?
  • 我明白了!谢谢大师!
  • 这里唯一严重的错误是名称应该以 NUL 分隔——否则,可以创建名为 $'local_dir/ \n/etc/foobar' 的目录的用户可以告诉远程脚本在 @987654338 下创建一个新目录@。在find 命令上使用-print0,在本地端使用while IFS='' read -r -d '',应该一切正常。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-01
  • 2016-02-02
  • 2020-07-22
相关资源
最近更新 更多