Java 使用kubernetes client exec()的PipeInputStream中断管道
我正在使用尝试从pod复制目录,但是我对stdout的输入流做了一些错误。我得到了一个Java 使用kubernetes client exec()的PipeInputStream中断管道,java,kubernetes,fabric8,Java,Kubernetes,Fabric8,我正在使用尝试从pod复制目录,但是我对stdout的输入流做了一些错误。我得到了一个java.io.IOException:当它尝试read()时,管道破裂了异常。我很确定根本没有数据流。我有点想知道我是否需要在单独的线程上读取InputStream或其他什么 流的创建方式如下: public InputStream copyFiles(String containerId, String folderName) { Exec
java.io.IOException:当它尝试read()
时,管道破裂了异常。我很确定根本没有数据流。我有点想知道我是否需要在单独的线程上读取InputStream或其他什么
流的创建方式如下:
public InputStream copyFiles(String containerId,
String folderName) {
ExecWatch exec = client.pods().withName(containerId).redirectingOutput().exec("tar -C " + folderName + " -c");
// We need to wrap the InputStream so that when the stdout is closed, then the underlying ExecWatch is closed
// also. This will cleanup any Websockets connections.
ChainedCloseInputStreamWrapper inputStreamWrapper = new ChainedCloseInputStreamWrapper(exec.getOutput(), exec);
return inputStreamWrapper;
}
private static class ChainedCloseInputStreamWrapper extends InputStream {
private InputStream delegate;
private Closeable resourceToClose;
public ChainedCloseInputStreamWrapper(InputStream delegate, Closeable resourceToClose) {
this.delegate = delegate;
this.resourceToClose = resourceToClose;
}
@Override
public int read() throws IOException {
return delegate.read();
}
public int available() throws IOException {
return delegate.available();
}
public void close() throws IOException {
logger.info("Shutdown called!");
delegate.close();
// Close our dependent resource
resourceToClose.close();
}
public boolean equals(Object o) {
return delegate.equals(o);
}
public int hashCode() {
return delegate.hashCode();
}
public int read(byte[] array) throws IOException {
return delegate.read(array);
}
public int read(byte[] array,
int n,
int n2) throws IOException {
return delegate.read(array, n, n2);
}
public long skip(long n) throws IOException {
return delegate.skip(n);
}
public void mark(int n) {
delegate.mark(n);
}
public void reset() throws IOException {
delegate.reset();
}
public boolean markSupported() {
return delegate.markSupported();
}
public String toString() {
return delegate.toString();
}
}
在这个函数中处理InputStream
void copyVideos(final String containerId) {
TarArchiveInputStream tarStream = new TarArchiveInputStream(containerClient.copyFiles(containerId, "/videos/"));
TarArchiveEntry entry;
boolean videoWasCopied = false;
try {
while ((entry = tarStream.getNextTarEntry()) != null) {
if (entry.isDirectory()) {
continue;
}
String fileExtension = entry.getName().substring(entry.getName().lastIndexOf('.'));
testInformation.setFileExtension(fileExtension);
File videoFile = new File(testInformation.getVideoFolderPath(), testInformation.getFileName());
File parent = videoFile.getParentFile();
if (!parent.exists()) {
parent.mkdirs();
}
OutputStream outputStream = new FileOutputStream(videoFile);
IOUtils.copy(tarStream, outputStream);
outputStream.close();
videoWasCopied = true;
LOGGER.log(Level.INFO, "{0} Video file copied to: {1}/{2}", new Object[]{getId(),
testInformation.getVideoFolderPath(), testInformation.getFileName()});
}
} catch (IOException e) {
LOGGER.log(Level.WARNING, getId() + " Error while copying the video", e);
ga.trackException(e);
} finally {
if (!videoWasCopied) {
testInformation.setVideoRecorded(false);
}
}
}
InputStream包装类仅用于在最后关闭ExecWatch
,一旦InputStream关闭,它如下所示:
public InputStream copyFiles(String containerId,
String folderName) {
ExecWatch exec = client.pods().withName(containerId).redirectingOutput().exec("tar -C " + folderName + " -c");
// We need to wrap the InputStream so that when the stdout is closed, then the underlying ExecWatch is closed
// also. This will cleanup any Websockets connections.
ChainedCloseInputStreamWrapper inputStreamWrapper = new ChainedCloseInputStreamWrapper(exec.getOutput(), exec);
return inputStreamWrapper;
}
private static class ChainedCloseInputStreamWrapper extends InputStream {
private InputStream delegate;
private Closeable resourceToClose;
public ChainedCloseInputStreamWrapper(InputStream delegate, Closeable resourceToClose) {
this.delegate = delegate;
this.resourceToClose = resourceToClose;
}
@Override
public int read() throws IOException {
return delegate.read();
}
public int available() throws IOException {
return delegate.available();
}
public void close() throws IOException {
logger.info("Shutdown called!");
delegate.close();
// Close our dependent resource
resourceToClose.close();
}
public boolean equals(Object o) {
return delegate.equals(o);
}
public int hashCode() {
return delegate.hashCode();
}
public int read(byte[] array) throws IOException {
return delegate.read(array);
}
public int read(byte[] array,
int n,
int n2) throws IOException {
return delegate.read(array, n, n2);
}
public long skip(long n) throws IOException {
return delegate.skip(n);
}
public void mark(int n) {
delegate.mark(n);
}
public void reset() throws IOException {
delegate.reset();
}
public boolean markSupported() {
return delegate.markSupported();
}
public String toString() {
return delegate.toString();
}
}
事实证明,我的tar命令错误,因此导致了故障,stdout PipeInputStream被死锁。我设法找到了解决僵局的办法。但失败的主要原因是我忘了告诉tar实际做些什么!我至少需要一个“.”来包含当前目录 结果是我的tar命令错误,因此导致了故障,stdout PipeInputStream被死锁。我设法找到了解决僵局的办法。但失败的主要原因是我忘了告诉tar实际做些什么!我至少需要一个“.”来包含当前目录 如何连接到apiserver?您是否正在通过集群中运行的kubectl代理连接?我正在集群中运行,使用创建了必要角色的服务帐户。如果有什么不同的话,我正在运行Openshift 1.4。我有另一个函数,它运行exec并写入输出流,工作正常:如何连接到apiserver?您是否正在通过集群中运行的kubectl代理连接?我正在集群中运行,使用创建了必要角色的服务帐户。如果有什么不同的话,我正在运行Openshift 1.4。我还有另外一个函数,它运行exec并写入outputstream,效果很好:你还记得你使用的完整tar命令吗?你还记得你使用的完整tar命令吗?