Java应用程序访问NFS共享

4
我正在尝试从Java应用程序内部访问CentOS 6.3系统上的NFS共享。 我尝试了以下库,但无法使其正常工作: YaNFS 使用YaNFS尝试访问NFS共享时,遇到NfsException错误代码10001(NFSERR_BADHANDLE)。有时异常文本会显示“过时的NFS文件句柄”。我的YaNFS代码如下:
    public static void main(String[] args) {
    XFile xf = new XFile("nfs://192.168.1.10/nfs-share");

    nfsXFileExtensionAccessor nfsx =
        (nfsXFileExtensionAccessor)xf.getExtensionAccessor();

        if (! nfsx.loginPCNFSD("192.168.1.10", "rpx-nfs-user", "Test123!")) {
             System.out.println("login failed");
             return;
        }

        if (xf.canRead())
             System.out.println("Read permission OK");
        else
             System.out.println("No Read permission");

}

nfs-client-java

尝试使用“nfs-client-java”初始化Nfs3对象时,我遇到了一个类似于MountException的异常:

com.emc.ecs.nfsclient.mount.MountException: mount failure, 
    server: 192.168.1.205, 
    export: /home/share, 
    nfs version: 3, 
    returned state: 13
at com.emc.ecs.nfsclient.nfs.nfs3.Nfs3.lookupRootHandle(Nfs3.java:359)

该点的状态为13,显示“权限被拒绝”。


我可以从另一个具有访问此文件夹 uid 和 gid 授权的 CentOS 系统以及具有访问此文件夹登录名和密码授权的 Windows 系统中挂载此共享并访问它。

是否有人已经解决了这个问题?或者有人可以帮助我进一步吗?


那么,为了明确起见,您可以从命令行挂载此nfs共享吗?如果可以,为什么不只是将其挂载,然后像本地文件一样从挂载点读取内容呢? - ashbygeek
很遗憾,这是不可能的,因为我不是运行我的应用程序的系统操作员。我猜操作员无法执行此操作是因为应用程序运行在集群系统中。当我提出挂载请求时,被拒绝了,因此我必须通过编程来实现它。 - AndySpu
你能发布一下你写的YaNFS代码吗?有异常是好的,但这只是战斗的一半。 - ashbygeek
我的 YaNFS 代码长这样:XFile xf = new XFile("nfs://192.168.1.10/nfs-share/test_file.txt"); 当我调用 canRead() 时,控制台输出 false。但是,我已经调试了代码,发现问题出在 Nfs3 类的 lookup 方法中,异常信息如上所述。 - AndySpu
你所说的“具有访问此文件夹的UID和GID授权”是什么意思?您需要用户名和密码才能从不同的系统访问共享吗? - ashbygeek
显示剩余2条评论
2个回答

1
该问题通过在共享上启用CIFS协议并使用旧的 JCIFS实现传输数据来解决。

那么这是否意味着我们可以使用CIFS/SMB协议访问NFS共享,例如使用像https://www.jcifs.org/,jcifs-codelibs这样的库? - Chidambaram Palaniappan

1
因此,您在评论中指出需要特定用户的权限才能访问文件,因此出现“权限被拒绝”错误。在YaNFS中,您需要查看nfsXFileExtensionAccessor以便发送用户名和密码以获取许可。这是我从此页面提取的示例: https://docs.oracle.com/cd/E19455-01/806-1067/6jacl3e6g/index.html
import java.io.*;
import com.sun.xfile.*;
import com.sun.nfs.*;

public class nfslogin {

     public static void main(String av[])
     {
          try {
               XFile xf = new XFile(av[0]);
               com.sun.nfsXFileExtensionAccessor nfsx =
               (com.sun.nfsXFileExtensionAccessor)xf.getExtensionAccessor();

               if (! nfsx.loginPCNFSD("pcnfsdsrv", "bob", "-passwd-")) {
                    System.out.println("login failed");
                    return;
               }

               if (xf.canRead())
                    System.out.println("Read permission OK");
               else
                    System.out.println("No Read permission");

          } catch (Exception e) {
            System.out.println(e.toString());
            e.printStackTrace(System.out);
          }
     }
}

编辑

不,我认为在登录操作之前不应该调用bind()。根据Github上的XFile源代码

 /*
 * Check that the file is open.
 * The open() method must be called before
 * any other methods in the Accessor.
 * This makes it easier for Accessors to
 * centralize initialization code in one place.
 */
private boolean bind() {
    if (bound)
        return true;

    bound = xfa.open(this, false, false);

    return bound;
}

由于bind()函数试图打开文件,因此在进行身份验证之前它将始终失败。然后考虑来自github上XFileExtensionAccessor代码的这段代码:

/**
 * Sets the user's RPC credential from Login name and password.
 *
 * Every NFS request includes a "credential" that identifies the user.
 * An AUTH_SYS credential includes the user's UID and GID values.
 * These are determined from the user's login name (and password)
 * by the PCNFSD service that must be available on a local server.
 * Once the credential is set, it is assigned globally to all
 * future NFS XFile objects.
 * <p>
 * If this method is not called, a default credential is assigned
 * with a UID and GID of "nobody".
 *
 * @param  <code>host</code> The name of the host that runs the PCNFSD service.
 *   This does not have to be an NFS server.
 * @param <code>username</code> The user's login name.
 * @param <code>password</code> The user's password.
 *   This is obscured before transmission to the PCNFSD server.
 * @return true if the login succeeded, false otherwise.
 */
public boolean loginPCNFSD(String host, String username, String password) {
    return NfsConnect.getCred().fetchCred(host, username, password);
}

因此,loginPCNFSD()函数会全局设置XFile系统的凭据,直到您注销或使用新的登录。在调用XFile.Bind()之前一定要调用它。


谢谢您提供这些信息。您尝试过这段源代码吗?我已经尝试过了,但是我无法绑定文件。在XFile类中有一个bind()方法。在执行任何操作之前(例如loginPCNFSD()),它将始终被调用。但是这个方法在我的情况下总是返回false。 - AndySpu
好的,由于我正在展示一些代码和其他东西,所以更新后的样式看起来真的很丑,因此我将只更新答案。 - ashbygeek
我使用uid和gid不是问题。我知道这些数据。"fetchCred"尝试使用一些Unix服务获取它们(顺便说一下,如果它没有运行,logil将获取root id来尝试)。我已经更新了我的源代码到YaNFS部分。在其中,我总是遇到System.out.println("login failed")消息。 - AndySpu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接