Skip to content

Commit 9fcf242

Browse files
authored
Merge pull request #31 from Typ0genius/main
Update executing commands code documentation
2 parents f8b7f2d + 7633393 commit 9fcf242

File tree

2 files changed

+52
-5
lines changed

2 files changed

+52
-5
lines changed

README.md

+41-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,47 @@ You can execute a command through SSH using the following code:
4444
let stdout = try await client.executeCommand("ls -la ~")
4545
```
4646

47-
The `executeCommand` function accumulated information into a contiguous `ByteBuffer`. This is useful for non-interactive commands such as `cat` and `ls`. Citadel currently does not expose APIs for streaming into a process' `stdin` or streaming the `stdout` elsewhere. If you want this, please create an issue.
47+
Additionally, a maximum responsive response size can be set, and `stderr` can be merged with `stdout` so that the answer contains the content of both streams:
48+
49+
```swift
50+
let stdoutAndStderr = try await client.executeCommand("ls -la ~", maxResponseSize: 42, mergeStreams: true)
51+
```
52+
53+
The `executeCommand` function accumulated information into a contiguous `ByteBuffer`. This is useful for non-interactive commands such as `cat` and `ls`.
54+
55+
The `executeCommandPair` function or `executeCommandStream` function can be used to access `stdout` and `stderr` independently. Both functions also accumulate information into contiguous separate `ByteBuffers`.
56+
57+
An example of how executeCommandPair can be used:
58+
59+
```swift
60+
let streams = try await client.executeCommandPair("cat /foo/bar.log")
61+
62+
for try await blob in answer.stdout {
63+
// do something with blob
64+
}
65+
66+
for try await blob in answer.stderr {
67+
// do something with blob
68+
}
69+
```
70+
71+
An example of how executeCommandStream can be used:
72+
73+
```swift
74+
let streams = try await client.executeCommandStream("cat /foo/bar.log")
75+
var asyncStreams = streams.makeAsyncIterator()
76+
77+
while let blob = try await asyncStreams.next() {
78+
switch blob {
79+
case .stdout(let stdout):
80+
// do something with stdout
81+
case .stderr(let stderr):
82+
// do something with stderr
83+
}
84+
}
85+
```
86+
87+
Citadel currently does not expose APIs for streaming into a process' `stdin`. If you want this, please create an issue.
4888

4989
### SFTP Client
5090

Sources/Citadel/TTY/Client/TTY.swift

+11-4
Original file line numberDiff line numberDiff line change
@@ -165,10 +165,11 @@ final class ExecCommandHandler: ChannelDuplexHandler {
165165
}
166166

167167
extension SSHClient {
168-
/// Executes a command on the remote server. This will return the output of the command. If the command fails, the error will be thrown. If the output is too large, the command will fail.
168+
/// Executes a command on the remote server. This will return the output of the command (stdout). If the command fails, the error will be thrown. If the output is too large, the command will fail.
169169
/// - Parameters:
170-
/// - command: The command to execute.
170+
/// - command: The command to execute.
171171
/// - maxResponseSize: The maximum size of the response. If the response is larger, the command will fail.
172+
/// - mergeStreams: If the answer should also include stderr.
172173
public func executeCommand(_ command: String, maxResponseSize: Int = .max, mergeStreams: Bool = false) async throws -> ByteBuffer {
173174
let promise = eventLoop.makePromise(of: ByteBuffer.self)
174175

@@ -217,7 +218,10 @@ extension SSHClient {
217218
return promise.futureResult
218219
}.get()
219220
}
220-
221+
222+
/// Executes a command on the remote server. This will return the output stream of the command. If the command fails, the error will be thrown.
223+
/// - Parameters:
224+
/// - command: The command to execute.
221225
public func executeCommandStream(_ command: String) async throws -> AsyncThrowingStream<ExecCommandOutput, Error> {
222226
var streamContinuation: AsyncThrowingStream<ExecCommandOutput, Error>.Continuation!
223227
let stream = AsyncThrowingStream<ExecCommandOutput, Error> { continuation in
@@ -258,7 +262,10 @@ extension SSHClient {
258262

259263
return stream
260264
}
261-
265+
266+
/// Executes a command on the remote server. This will return the pair of streams stdout and stderr of the command. If the command fails, the error will be thrown.
267+
/// - Parameters:
268+
/// - command: The command to execute.
262269
public func executeCommandPair(_ command: String) async throws -> ExecCommandStream {
263270
var stdoutContinuation: AsyncThrowingStream<ByteBuffer, Error>.Continuation!
264271
var stderrContinuation: AsyncThrowingStream<ByteBuffer, Error>.Continuation!

0 commit comments

Comments
 (0)