Spring 批处理项目。sshiservice接受ssh命令并执行它们。当项目在jenkins管道中运行时,它能够创建ssh连接,而我的sshiservice运行得很好。
在为这个sshiservice服务编写集成测试时,我创建了一个虚拟ssh服务器,这个服务可以与之对话。
问题:在集成测试中,当我发送如下命令时 mkdir src/test/resources/Folder1 ; ls src/test/resources/Folder1 ;
错误是:
mkdir: ls: File exists
mkdir: src/test/resources/Folder1: File exists
mkdir: ;: File exists
该服务并不认为这些是单独的命令,而是作为 mkdir
这是错误的!这个问题不是特定于 mkdir
. 每次在集成测试中执行多个由分号分隔的命令时,就会出现问题。
我不想对sshiservice进行更改,因为整个项目都在使用这种逻辑。问题似乎出现在为集成测试创建的ssh服务器中。
集成测试代码
@SpringBootTest
@ContextConfiguration(classes = {SshIService.class, SshSftpConfiguration.class})
@ActiveProfiles("test")
public class SshSftpIntegrationTest {
@Autowired
private SshIService SshIService;
private SshServer dummy_sshd;
@SneakyThrows
@BeforeEach
public void setUp() {
dummy_sshd = SshServer.setUpDefaultServer();
dummy_sshd.setPort(9999);
dummy_sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider());
dummy_sshd.setPasswordAuthenticator((username, password, session) -> username.equals("someUserName") && password.equals("somePassword"));
dummy_sshd.setSubsystemFactories(Collections.singletonList(new SftpSubsystemFactory()));
dummy_sshd.setCommandFactory(new ProcessShellCommandFactory());
dummy_sshd.start();
}
@SneakyThrows
@AfterEach
public void cleanup() {
dummy_sshd.stop();
}
@SneakyThrows
@Test
public void sendCommandTest() {
SshIService.sendCommand("mkdir src/test/resources/Folder1 ; ls src/test/resources/Folder1 ;");
//Some assertions!
}
}
sshiservice代码
@Slf4j
@Service
public class SshIService {
private final SshSftpConfiguration sshSftpConfiguration;
private final JSch sshTunnel;
private Session sshSession;
private ChannelSftp channelSftp;
public SshIService(SshSftpConfiguration sshSftpConfiguration,
JSch sshTunnel) {
this.sshSftpConfiguration = sshSftpConfiguration;
this.sshTunnel = sshTunnel;
}
public String sendCommand(String command) throws IOException, JSchException, InterruptedException {
try {
connect();
Channel channel = sshSession.openChannel("exec");
((ChannelExec) channel).setCommand(command);
channel.setInputStream(null);
((ChannelExec) channel).setErrStream(System.err);
InputStream in = channel.getInputStream();
channel.connect();
StringBuilder output = new StringBuilder();
int bytesRead;
byte[] buffer = new byte[1024];
while (!channel.isClosed()) {
while ((bytesRead = in.read(buffer, 0, buffer.length)) != -1) {
output.append(new String(buffer, 0, bytesRead));
}
Thread.sleep(100);
}
channel.disconnect();
return cmdOut;
} catch (IOException | JSchException | InterruptedException ioX) {
log.error("Error: {}", ioX.getMessage());
throw ioX;
}
}
public String getHostAddress() throws UnknownHostException {
return InetAddress.getLocalHost().getHostAddress();
}
public void connect() {
try {
if (sshSession == null || !sshSession.isConnected()) {
sshSession = sshTunnel.getSession(sshSftpConfiguration.getUsername(), sshSftpConfiguration.getHost());
sshSession.setPort(sshSftpConfiguration.getPort());
sshSession.setPassword(sshSftpConfiguration.getPassword());
sshSession.setConfig("StrictHostKeyChecking", "no");
}
if (sshSession != null && !sshSession.isConnected()) {
sshSession.connect();
}
if (sshSession != null && channelSftp == null || !channelSftp.isConnected()) {
channelSftp = (ChannelSftp) sshSession.openChannel("sftp");
channelSftp.connect();
}
} catch (JSchException e) {
log.error(ExceptionUtils.getStackTrace(e));
}
}
public ChannelSftp getChannelSftp() {
return channelSftp;
}
public void setChannelSftp(ChannelSftp channelSftp) {
this.channelSftp = channelSftp;
}
public Session getSshSession() {
return sshSession;
}
public void setSshSession(Session sshSession) {
this.sshSession = sshSession;
}
}
有什么建议吗?
2条答案
按热度按时间omvjsjqw1#
您不是通过ssh连接到一个真正的服务器,而是连接到一个apacheminash服务器,只有一个sftp子系统。
这并不意味着它可以接受任意的os/shell命令。
https://mina.apache.org/sshd-project/
sshd的目标并不是真正取代unix操作系统中的ssh客户机或ssh服务器,而是为需要ssh支持的基于java的应用程序提供支持。
siotufzp2#
试试sshiservice.sendcommand(“mkdir src/test/resources/folder1&&ls src/test/resources/folder1”);