dartssh2 icon indicating copy to clipboard operation
dartssh2 copied to clipboard

Output of remote "tail - f"

Open illuminated opened this issue 2 years ago • 2 comments

Can someone please provide an example of gathering a continuous stream of string lines from a remotely executed "tail - f"?

illuminated avatar Jun 18 '22 20:06 illuminated

Hi, thanks for your interest in this package! To spawn a process and listen to its output, simply use SSHClient.execute as follows:

final client = SSHClient(...);

final session = await client.execute('tail -f path/to/file');

await for (final chunk in session.stdout.cast<List<int>>().transform(Utf8Decoder())) {
  print('got: $chunk');
}

xtyxtyx avatar Jun 19 '22 12:06 xtyxtyx

Thanks a lot @xtyxtyx for the reply!

I made the following solution that worked for me, just wasn't sure if it was the best possible one. I have "misused" the fact that stdout returns buffered list of characters, containing at least one whole line, or more.

  List<String> outputLines = [];

  Future<SSHClient> connect() async {
    return SSHClient(
        await SSHSocket.connect(host!, port!), 
        username: username!, 
        onPasswordRequest: () => password!,
      );
  }

  Stream<Uint8List> tailf() async* {
    final connection = await connect();
    final client = await connection.execute('tail -f /var/log/some.log');
    yield* client.stdout;
  }

  void output() {
    tailf().listen((event) {
      final output = utf8.decode(event);
      const lineSplitter = LineSplitter();
      final lineBuffer = lineSplitter.convert(output);

      for (var x = 0; x < lineBuffer.length; x++) {
        outputLines.add(lineBuffer[x]);
        log('New line: ${lineBuffer[x]}');
        // Here goes the code where the output can be added to a state management solution of choice
      }
      });
  }

In case the output is slower and buffer contains less than a full line, I'd have to listen to stderr output, I guess, as it sends each character separately, then populate the lineBuffer until the received character is new line (RegExp(r'\n')) and then add it to outputLines...

Anyway, kudos for the work on this package, I've picked it specifically as it's a pure Dart implementation and, therefore, it's the easiest for cross-platform migration.

Edit: forgot to add: your solution is much more elegant!

illuminated avatar Jun 19 '22 18:06 illuminated