【问题标题】:JavaNIO: check File lock created by a root-user from a process running under a normal user?JavaNIO:检查root用户从普通用户下运行的进程创建的文件锁?
【发布时间】:2012-05-07 20:06:49
【问题描述】:

我有两个要同步的进程。

进程 A 以 root 身份运行并在特定文件上创建可重入锁。 进程 B 在“普通”用户下运行,应该等待进程 A 释放锁。

我尝试了很多方法,但由于文件权限错误,无法使其正常工作。 这是代码: (删除了虚拟机内同步的东西):

锁定:

FileChannel channel = new RandomAccessFile(pFile, "rw").getChannel();
lock = channel.tryLock();

有锁:

RandomAccessFile file = new RandomAccessFile(pFile, "rw");
FileChannel channel = file.getChannel();
FileLock lock = channel.tryLock();
if (lock == null) {
 return true;
}
lock.release();

我遇到的问题是锁被创建为:

-rw-r--r--. 1 root root 0 May  7 21:42 lockfile.lock

如果我尝试检查锁(通过以普通用户身份运行的进程 B)我得到一个

java.io.FileNotFoundException: _lockfile_ (Permission denied)
    at java.io.RandomAccessFile.open(Native Method)
    at java.io.RandomAccessFile.<init>(RandomAccessFile.java:212)

我试图将目录隐藏到所有 g=rwx,o=rwx 但这似乎被忽略了。我尝试先创建文件 setWritable(true, false) 但这似乎已重置。我没有任何方法可以工作。我尝试在 hasLock 中使用模式“r”而不是“rw”,但这会导致 ChannelNotWritableException。

所以主要问题是:如何影响创建的锁文件的权限?

有人有什么建议吗?

问候迈克尔

【问题讨论】:

  • 我过去所做的是通过为数据文件中的所有记录建立一个索引文件来避免对锁的需求。这允许进程之间的并发访问(前提是你只有一个作家)
  • 我不需要写任何东西。我只需要检查其他进程是否仍在运行(持有锁)。对于一些“等到完成”的方法。我在一个无状态的 web 服务中,它必须在启动其他断开连接的进程时使进程死亡。我可以猜出文件名,因为这是可以用参数构造出来的。

标签: java permissions locking nio


【解决方案1】:

您遇到了根进程的umask,它掩盖了您在创建文件时提供的“rw”以拒绝对groupothers 的写访问。除了更改根的umask 之外,您无能为力,出于安全原因,这是一个非常糟糕的主意。

您应该考虑让锁定文件永久存在,或者按照 Peter 的建议,使用已经是您应用程序一部分的文件作为锁定文件。

【讨论】:

  • 我理解正确吗,除了目录的umask,进程本身也有一个umask,这是“降级”权限?确实,更改根 umask 不是一种选择。
  • 感谢您迄今为止的建议。澄清问题:进程 B 是一个 Web 服务,它启动进程 A(使用 sudo 以 root 身份)。进程 A 返回一个标识符(通过 Sysout),它也是锁定文件的名称。 Web 服务将此标识符返回给调用者。通过另一种方法,调用者应该能够检查进程 A 是否已完成(或等到完成)。这就是锁的用途。进程 A 可能会并行运行多次(使用不同的标识符)所以我不能使用已经存在的文件:-(
  • @user1380578 (1) 您根本不应该以 root 身份启动进程。 (2) 你有 Process.waitFor() 和 Process.exitValue():你为什么需要一个锁文件?
  • 我需要以 root 身份启动进程 A(因为它确实对系统进行了更改,只有 root 允许)但我不希望 web 服务以 root 身份运行(正如你所说的那样)。调用它的 web 服务是无状态的(并且应该有几个原因),因此进程对象在调用之间丢失。锁定文件用于恢复状态。文件被锁定 = 进程仍在运行,文件不存在 = 进程完成(状态也基于标识符写入信息文件)。 InfoFile 存在 = 进程已完成,Lockfile 存在且未锁定,没有 infofile = 进程死亡,依此类推。
  • @user 那你为什么不能调用我提到的 API 呢?
【解决方案2】:

终于找到了解决办法:

首先创建文件的方式是正确的。我犯的错误是我在创建文件之前设置了权限(期望权限存储在文件对象中并在创建时使用)。我必须先创建文件,然后将权限设置为 all 然后锁定它:

file.createNewFile();
file.setWritable(true, false);
FileChannel channel = new RandomAccessFile(file, "rw").getChannel();
channel.tryLock()

现在使用 worlwide-writable 创建了锁定文件(这可能是一个安全问题,但实际上没有可见问题,因为该文件不包含任何内容。

感谢所有帮助我找到解决方案的人!

问候迈克尔

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-28
    • 1970-01-01
    • 1970-01-01
    • 2015-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-05
    相关资源
    最近更新 更多