You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多层转义场景下保留引号实现z/OS MVS数据集cp复制问题求解

z/OS USS cp命令引号转义问题修复方案

根因定位

报错cp: target "//'WOODSMN.SSC.D051721.T200335.S90.CP037'" is not a directory由两个核心问题导致:

  • 命令作用域错误:ssh远程执行的多命令没有整体包裹,export _UNIX03=NO;后的cp命令实际在本地Docker的bash环境执行,自然无法识别MVS数据集路径
  • 多层转义丢失:Perl、本地Docker bash、远程z/OS Korn shell三层环境都会消耗一层转义符,手动编写的转义层数不足,引号被提前解析消耗,cp命令拿到的目标路径格式不符合要求

修复方案

1. 修正远程命令作用域

ssh执行多命令时,需要把所有要在远程运行的命令用引号整体包裹,避免本地shell拆分执行:

# 修改RunSshCommand调用逻辑,将远程命令整体包裹
RunSshCommand(shell_quote("export _UNIX03=NO;cp ${OPTIONS} ${FULLY_QUALIFIED_HFS_FILE} ${FULLY_QUALIFIED_MVS_ARGUMENT}"));

2. 修正数据集目标路径转义

z/OS要求的最终cp参数格式为"//'数据集全称'",需增加转义层数确保三层解析后仍保留正确格式:

# 替换putMvsFileByHfs函数中的目标路径构建代码
my $FULLY_QUALIFIED_MVS_ARGUMENT = qq(\\"//\\'$FULLY_QUALIFIED_MVS_FILE\\'\\");

3. 修正-P参数转义

原-P参数中的括号转义层数不足,调整后代码如下:

my $MVS_FORMAT_OPTIONS = qq(-P "RECFM=FB,LRECL=287,BLKSIZE=6027,SPACE=\\\\($SSCJCL_STORAGE_UNIT,\\\\($SSCJCL_PRIMARY_EXTENTS,$SSCJCL_SECONDARY_EXTENTS\\\\))\\\\");

Perl代码优化建议

  • 普通变量引用无需加${}包裹,直接写$变量名即可,符合Perl编码规范
  • 推荐使用String::ShellQuote模块的shell_quote函数自动处理shell转义,避免手动转义遗漏
  • 封装的RunScpCommand、RunSshCommand函数不要硬编码全局变量,改为参数传递可提升复用性
  • 变量命名无需全部大写,小写下划线分隔的命名方式可读性更高

修复后核心代码示例

use strict;
use warnings;
use String::ShellQuote qw(shell_quote);
use IPC::Run3;

# 全局变量定义部分保持不变
my $SSCJCL_SOURCE_DIRECTORY = "/home/bluecost/";
my $SSCJCL_STORAGE_UNIT = "TRACK";
my $SSCJCL_PRIMARY_EXTENTS = "1";
my $SSCJCL_SECONDARY_EXTENTS = "1";
my $SSCJCL_HFS_LOCATION="/u/woodsmn";
my $SSCJCL_STAGING_HLQ = "WOODSMN";
my $COST_FILE="SSC.D051721.T200335.S90.CP037";
my $SSCJCL_USER_PW="mypass";
my $SSCJCL_USER_ID="woodsmn";
my $SSCJCL_HOST_NAME="bldbmsb.boulder.mycompany.com";

sub putMvsFileByHfs {
    my ($options, $local_file, $hfs_file, $mvs_file) = @_;
    RunScpCommand($local_file, $hfs_file);

    my $mvs_target = "//'$mvs_file'";
    my $remote_cmd = join ';', (
        'export _UNIX03=NO',
        "cp $options $hfs_file " . shell_quote($mvs_target)
    );
    RunSshCommand(shell_quote($remote_cmd));
}

sub RunScpCommand {
    my ($source, $target) = @_;
    my ($out, $err);
    my $full_cmd = "sshpass -p $SSCJCL_USER_PW scp $source $SSCJCL_USER_ID\@$SSCJCL_HOST_NAME:$target";
    print $full_cmd."\n";
    run3 $full_cmd, undef, \$out, \$err;
    print $out."\n".$err."\n";
    return ($out, $err);
}

sub RunSshCommand {
    my ($cmd) = @_;
    my ($out, $err);
    my $full_cmd = "sshpass -p $SSCJCL_USER_PW ssh $SSCJCL_USER_ID\@$SSCJCL_HOST_NAME $cmd";
    print $full_cmd."\n";
    run3 $full_cmd, undef, \$out, \$err;
    print $out."\n".$err."\n";
    return ($out, $err);
}

# 调用示例
my $MVS_FORMAT_OPTIONS = qq(-P "RECFM=FB,LRECL=287,BLKSIZE=6027,SPACE=($SSCJCL_STORAGE_UNIT,($SSCJCL_PRIMARY_EXTENTS,$SSCJCL_SECONDARY_EXTENTS))");
putMvsFileByHfs(
    $MVS_FORMAT_OPTIONS,
    "$SSCJCL_SOURCE_DIRECTORY/$COST_FILE",
    "$SSCJCL_HFS_LOCATION/$COST_FILE",
    "$SSCJCL_STAGING_HLQ.$COST_FILE"
);

内容的提问来源于stack exchange,提问作者Woodsman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.15 03:45:01