JSch SFTP 放入 IBM z/OS 失败:无法写入文件;嵌套异常为 3:权限被拒绝

Posted

技术标签:

【中文标题】JSch SFTP 放入 IBM z/OS 失败:无法写入文件;嵌套异常为 3:权限被拒绝【英文标题】:JSch SFTP put to IBM z/OS fails :failed to write file; nested exception is 3: Permission denied 【发布时间】:2016-06-08 16:49:33 【问题描述】:

我正在尝试使用 JSch 通过 SFTP 将文件放入大型机。

代码如下:

public void uploadFile(String contents) throws Exception 
    JSch.setLogger(new JSCHLogger());
    connectIfDisconected();
    LOGGER.info("Channel isConnected=: " + channel.isConnected());
    OutputStream os = channel.put("//!DTS4.UP.G5TB4.S60301");
    os.write(contents.getBytes());
    os.flush();
    os.close();


protected void connectIfDisconected() throws JSchException 
    if (!session.isConnected()) 
        LOGGER.info(LogEvent.create(".connectIfDisconected()", "Reconnecting session and channel..."));
        session.connect();
        if (channel != null) 
            channel.exit();
        
        channel = (ChannelSftp) session.openChannel("sftp");
     else if (!channel.isConnected()) 
        LOGGER.info(LogEvent.create(".connectIfDisconected()", "Reconnecting channel..."));
        channel.connect();
    

这是会话配置:

session = jsch.getSession(username, host, port);
Properties config = getProperties(host, port);
session.setConfig(config);
...
...
protected Properties getProperties(String host, int port) throws JSchException 
    Properties config = new Properties();
    config.put("StrictHostKeyChecking", strictHostChecking ? "yes" : "no");
    config.put("kex", "diffie-hellman-group-exchange-sha1");
    config.put("PreferredAuthentications", "password");
    return config;

会话连接正常!

当我尝试放置文件时,我在线上遇到了以下异常

OutputStream os = channel.put(targetFile);
com.three60t.tex.app.exceptions.business.BusinessException: Error while delivering to Client communicator : Permission denied
        at com.three60t.integration.posttrade.utils.DefaultReporter.reportError(DefaultReporter.java:68)
        at com.three60t.integration.posttrade.transformationService.InternalTransformationService.reportError(InternalTransformationService.java:439)
        at com.three60t.integration.posttrade.transformationService.InternalTransformationService.deliver(InternalTransformationService.java:378)
        at com.three60t.integration.posttrade.transformationService.InternalTransformationService.doDeliver(InternalTransformationService.java:314)
        at com.three60t.integration.posttrade.transformationService.InternalTransformationService.transform(InternalTransformationService.java:305)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at com.three60t.tex.communication.message.handler.MessageDispatcher.dispatchToObject(MessageDispatcher.java:722)
        at com.three60t.tex.communication.message.handler.MessageDispatcher.doExecuteObject(MessageDispatcher.java:543)
        at com.three60t.tex.communication.message.handler.MessageDispatcher.access$200(MessageDispatcher.java:77)
        at com.three60t.tex.communication.message.handler.MessageDispatcher$1.run(MessageDispatcher.java:264)
        at com.three60t.tex.communication.message.handler.MessageDispatcher$3.run(MessageDispatcher.java:444)
        at com.three60t.concurrent.executor.v2.RunnableWithTimings.run(RunnableWithTimings.java:81)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
Caused by: 3: Permission denied
        at com.jcraft.jsch.ChannelSftp.throwStatusError(ChannelSftp.java:2846)
        at com.jcraft.jsch.ChannelSftp.put(ChannelSftp.java:753)
        at com.jcraft.jsch.ChannelSftp.put(ChannelSftp.java:700)
        at com.jcraft.jsch.ChannelSftp.put(ChannelSftp.java:694)
        at com.three60t.integration.tradeimporters.sftp.DtccSftpClient.uploadFile(DtccSftpClient.java:34)
        at com.three60t.integration.tradeimporters.sftp.SFTPTransportDtcc.upload(SFTPTransportDtcc.java:41)
        at com.three60t.framework.communication.integration.SFTPTransport.upload(SFTPTransport.java:148)
        at com.three60t.integration.tradeimporters.sftp.SFTPTransportDtcc.upload(SFTPTransportDtcc.java:25)
        at com.three60t.integration.tradeimporters.sftp.SFTPTransportDtcc.deliver(SFTPTransportDtcc.java:55)
        at com.three60t.integration.posttrade.transformationService.InternalTransformationService.deliver(InternalTransformationService.java:362)
        ... 15 more

当我使用终端尝试相同时,一切正常!

sftp XXXX@fdmoverspse.dtcc.com
Connecting to fdmoverspse.dtcc.com...
XXXX@fdmoverspse.dtcc.com's password: 
sftp> put myfile.xml //!DTS4.UP.G5TB4.S60301
Uploading myfile.xml to //!DTS4.UP.G5TB4.S60301
myfile.xml       100% 7901     7.7KB/s   00:00   
sftp>

任何想法如何解决?

【问题讨论】:

【参考方案1】:

如果路径以两个斜杠开头,ChannelSftp.glob_remote 中有一个“错误”会去除第二个斜杠。

而不是这个:

if(!pattern_has_wildcard)
  if(!dir.equals("/"))
    dir+="/";
  v.addElement(dir+Util.unquote(_pattern));
  return v;

代码应该是这样的:

if(!pattern_has_wildcard)
  if(foo != 0)
    dir+="/";
  v.addElement(dir+Util.unquote(_pattern));
  return v;

【讨论】:

太棒了!谢谢!将尝试报告该错误! 看起来用 3 个斜杠放置文件可能有效 ///!DTS4.UP.G5TB4.S60301【参考方案2】:

我能够使用sshj 放置文件。有一个适合我的简单客户端:

public class DtccSftpSshjClient 

private static final Logger LOGGER = Log.getLogger(DtccSftpSshjClient.class);
private String hostname;
private String username;
private String password;

private SSHClient client;


public DtccSftpSshjClient(String hostname, String username, String password) throws IOException 
    this.hostname = hostname;
    this.username = username;
    this.password = password;
    client = new SSHClient();
    client.addHostKeyVerifier(new PromiscuousVerifier());
    client.connect(hostname);
    client.authPassword(username, password);


public void upload(String refId, String message, String dest) 
    try 
        LocalSourceFile messageFile = new InMemoryTradeFile(message, refId);
        SFTPClient sftp = client.newSFTPClient();
        sftp.put(messageFile, dest);
        sftp.close();
     catch (Exception e) 
        LOGGER.error(e.toString());
    



public void closeConnection() throws IOException 
    client.disconnect();


private class InMemoryTradeFile extends InMemorySourceFile 

    String message;
    String refId;

    public InMemoryTradeFile(String message, String refId) 
        this.message = message;
        this.refId = refId;
    

    @Override
    public String getName() 
        return refId;
    

    @Override
    public long getLength() 
        return message.getBytes().length;
    

    @Override
    public InputStream getInputStream() throws IOException 
        return new ByteArrayInputStream(message.getBytes());
    


希望这会有所帮助。

【讨论】:

以上是关于JSch SFTP 放入 IBM z/OS 失败:无法写入文件;嵌套异常为 3:权限被拒绝的主要内容,如果未能解决你的问题,请参考以下文章

常春藤安装任务第一次失败并出现 JSCH SFTP 错误 4,但在后续尝试中成功

jsch实现java sftp上传,在非root用户下出现permission dined异常,

JSchException:算法协商失败

使用 SFTP 连接到 z/OS 大型机

jsch的sftp在多线程下的问题及处理办法

使用 jsch 库在 sftp 中复制文件