当作为非特权用户运行Files.walk(Paths.get("/var/")).count()
时,执行可能会抛出异常,因为/var/
中的文件夹需要遍历root权限。
我 不 正在寻找以root身份执行bash命令的方法(例如sudo find /var
),使用Process
等。< / p>
我只是想确保Files.walk(Paths.get("/var/")).count()
不会抛出AccessDeniedException
:
Exception in thread "restartedMain" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0
at sun.reflect.NativeMethodAccessorImpl.invoke
at sun.reflect.DelegatingMethodAccessorImpl.invoke
at java.lang.reflect.Method.invoke
at org.springframework.boot.devtools.restart.RestartLauncher.run
Caused by: java.io.UncheckedIOException: java.nio.file.AccessDeniedException: /var/cache/httpd
at java.nio.file.FileTreeIterator.fetchNextIfNeeded
at java.nio.file.FileTreeIterator.hasNext
at java.util.Iterator.forEachRemaining
at java.util.Spliterators$IteratorSpliterator.forEachRemaining
at java.util.stream.AbstractPipeline.copyInto
at java.util.stream.AbstractPipeline.wrapAndCopyInto
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential
at java.util.stream.AbstractPipeline.evaluate
at java.util.stream.LongPipeline.reduce
at java.util.stream.LongPipeline.sum
at java.util.stream.ReferencePipeline.count
at com.example.DemoApplication.main
... 5 more
Caused by: java.nio.file.AccessDeniedException: /var/cache/httpd
at sun.nio.fs.UnixException.translateToIOException
at sun.nio.fs.UnixException.rethrowAsIOException
at sun.nio.fs.UnixException.rethrowAsIOException
at sun.nio.fs.UnixFileSystemProvider.newDirectoryStream
at java.nio.file.Files.newDirectoryStream
at java.nio.file.FileTreeWalker.visit
at java.nio.file.FileTreeWalker.next
at java.nio.file.FileTreeIterator.fetchNextIfNeeded
这只是一个例子。使用filter(...)
可以解决异常问题。但是这个例子也可以扩展到其他用例。
所以简而言之这是否可行,CLI,JavaFX等应用程序在通过java -jar app.jar
等方法从命令行执行后获得root权限?
答案 0 :(得分:9)
如果你想要的实际上是跳过你无法访问的路径,你有两种方法:
<强>流强>
In the answer to this question解释了如何获取可以访问的子树的所有文件的流。
但是这个例子也可以扩展到其他用例。
<强> FileVisitor的强>
使用FileVisitor
添加了大量代码,但在遍历目录树时可以更灵活。要解决同样的问题,您可以将Files.walk()
替换为:
Files.walkFileTree(Path start, FileVisitor<? super Path> visitor);
扩展SimpleFileVisitor(计算文件)并覆盖某些方法。
你可以:
visitFileFailed
方法,以处理因某些原因无法访问文件的情况; (Lukasz_Plawny的建议)preVisitDirectory
方法,在访问目录之前检查权限:如果您无法访问该目录,则可以跳过其子树(请记住,您可以访问该子树)一个目录,但不是它的所有文件); e.g。 1
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) {
// you can log the exception 'exc'
return FileVisitResult.SKIP_SUBTREE;
}
e.g。 2
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
if(!Files.isReadable(dir))
return FileVisitResult.SKIP_SUBTREE;
return FileVisitResult.CONTINUE;
}
希望它有所帮助。
答案 1 :(得分:3)
一些完全没有经过考验的想法:
1)以root权限运行您的应用程序:
sudo java -jar myapp.jar
2)让您的应用启动一个请求root权限的启动器类,然后继续运行您应用的其余部分:
java -jar myapp.jar
这反过来执行一个shell命令,但只有一个提示root密码的xterm,然后继续运行具有root权限的java程序:
xterm -e "sudo sh -c 'java -jar /tmp/myrootapp.jar'"
或者使用gksudo使用更好看的东西。注意'
和"
。
也许myapp.jar
将自己摘录为temporary directory。 myapp.jar
包含myrootapp.jar
,因此可以按上述方式启动它。当然应该从java中检索/tmp
,最好是一个具有随机名称的目录,只有运行myapp.jar
的用户才能访问,以防止myrootapp.jar
注入。
<强>跨平台强>
你自己提到/var/
,所以我以为你是在某种Linux上。如果这应该跨平台工作,例如在Macintosh或Microsoft Windows上,您需要先进行某种系统识别。然后,您可以在代码中应用StrategyPattern来处理让myrootapp.jar
获得root权限或管理员权限的各种方法。
答案 2 :(得分:2)
没有简单的方法来更改权限。 Java并不擅长这些任务。在启动时只有一些技巧,如检查权限,并尝试通过su / sudo更改权限,然后重新启动应用程序或使用Java-gnome。请在此处阅读更多内容:Java: Ask root privileges on Ubuntu