public CancellationTokenSource StartLogs(DockerClient client, string id, Action <string, string, long> backCall = null) { var cancellationTokenSource = new CancellationTokenSource(); var progress = new Progress <string>(); var queue = new ConcurrentQueue <string>(); var key = RedisKeys.SentryList(SentryEnum.Log, id); // 重置这个redis _redis.KeyDelete(key); progress.ProgressChanged += (obj, message) => { queue.Enqueue(message); }; _ = Task.Run(async() => // 每 5ms 存储一次 { while (true) { if (queue.TryDequeue(out var message)) { var rule = "[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{9}Z"; var time = Regex.Matches(message, rule)[0].Value; var v = message.Split(new[] { time }, StringSplitOptions.None)[1] .Replace("\u001b[40m\u001b[1m\u001b[33mwarn\u001b[39m\u001b[22m\u001b[49m:", "[warn]") .Replace("\u001B[41m\u001B[30mfail\u001B[39m\u001B[22m\u001B[49m", "[fail]"); var l = _redis.ListRightPush(key, new { time, log = v }); if (backCall != null) { backCall(id, v, l); } } await Task.Delay(5); } }, cancellationTokenSource.Token); _ = client.Containers.GetContainerLogsAsync( id, new ContainerLogsParameters { // as the error said, you have to choose one stream either stdout or stderr. If you don't input any of these option to be true, it would panic. ShowStdout = true, ShowStderr = true, Timestamps = true, Follow = true }, cancellationTokenSource.Token, progress ); return(cancellationTokenSource); }