コード例 #1
0
        public static async Task InvokeCommand(
            ContainerExecCreateParameters parameters,
            IImageSettings settings)
        {
            ContainerExecCreateResponse response = await _client.Containers
                                                   .ExecCreateContainerAsync(
                settings.ContainerId,
                parameters);

            if (!string.IsNullOrEmpty(response.ID))
            {
                using (MultiplexedStream stream = await _client.Containers
                                                  .StartAndAttachContainerExecAsync(
                           response.ID, false))
                {
                    (string stdout, string stderr)output = await stream
                                                           .ReadOutputToEndAsync(CancellationToken.None);

                    if (!string.IsNullOrEmpty(output.stderr) && output.stderr.Contains("error"))
                    {
                        var error = new StringBuilder();
                        error.AppendLine($"Error when invoking command \"{string.Join(" ", parameters.Cmd)}\"");
                        error.AppendLine(output.stderr);

                        throw new ContainerException(error.ToString());
                    }
                }
            }
        }
コード例 #2
0
        internal static async Task StartContainerAsync(
            DockerClient client,
            string containerId,
            ContainerAttachParameters attachParams,
            bool?isTTY,
            ContainerStartParameters startParams,
            CancellationToken token)
        {
            MultiplexedStream stream = null;
            Task streamTask          = null;

            try
            {
                if (attachParams != null)
                {
                    stream = await client.Containers.AttachContainerAsync(containerId, isTTY.GetValueOrDefault(), attachParams, token);

                    streamTask = stream.CopyToConsoleAsync(isTTY.GetValueOrDefault(), attachParams.Stdin.GetValueOrDefault(), token);
                }

                if (!await client.Containers.StartContainerAsync(containerId, new ContainerStartParameters()))
                {
                    throw new ApplicationFailedException("The container has already started.");
                }

                if (attachParams != null)
                {
                    await streamTask;
                }
            }
            finally
            {
                stream?.Dispose();
            }
        }
コード例 #3
0
    public static async Task PipeContainerOutput(IOutputObserver outputObserver, MultiplexedStream stream, CancellationToken cancellationToken)
    {
        byte[] buffer = new byte[1024];
        while (!cancellationToken.IsCancellationRequested)
        {
            var result = await stream.ReadOutputAsync(buffer, 0, buffer.Length, cancellationToken);

            if (result.EOF)
            {
                break;
            }

            switch (result.Target)
            {
            case MultiplexedStream.TargetStream.StandardOut:
                await outputObserver.StandardOutput(buffer, result.Count);

                break;

            case MultiplexedStream.TargetStream.StandardError:
                await outputObserver.StandardError(buffer, result.Count);

                break;
            }
        }
    }
コード例 #4
0
        public static async Task CopyToConsoleAsync(this MultiplexedStream stream, bool tty, bool openStdin, CancellationToken cancellationToken)
        {
            Stream        stdin = Stream.Null, stdout = Stream.Null, stderr = Stream.Null;
            ConsoleStream conin = null, conout = null;

            try
            {
                // TODO: What if we are not attached to a console? If config.Tty is false, this should not be an error.
                conout = new ConsoleStream(ConsoleDirection.Out);
                stdout = Console.OpenStandardOutput(); // Don't use conout's Stream because FileStream always buffers on net46.
                if (tty)
                {
                    conout.EnableVTMode();
                }
                else
                {
                    stderr = Console.OpenStandardError();
                }

                Task stdinRead = null;
                CancellationTokenSource inputCancelToken = null;
                if (openStdin)
                {
                    conin = new ConsoleStream(ConsoleDirection.In);
                    stdin = conin.Stream;
                    conin.EnableRawInputMode();
                    if (tty)
                    {
                        conin.EnableVTMode();
                    }

                    inputCancelToken = new CancellationTokenSource();
                    stdinRead        = stream.CopyFromAsync(stdin, inputCancelToken.Token).ContinueWith(x => stream.CloseWrite());
                }

                await stream.CopyOutputToAsync(stdout, stdout, stderr, cancellationToken).ConfigureAwait(false);

                if (stdinRead != null)
                {
                    inputCancelToken.Cancel();
                    try
                    {
                        await stdinRead.ConfigureAwait(false);
                    }
                    catch (TaskCanceledException)
                    {
                        // Ignore.
                    }
                }
            }
            finally
            {
                conin?.Dispose();
                conout?.Dispose();
                stdin.Dispose();
                stdout.Dispose();
                stderr.Dispose();
            }
        }
コード例 #5
0
ファイル: DockerService.cs プロジェクト: vblz/TankFight
        public async Task <ContainerOutput> ReadLineAsync(MultiplexedStream multiplexedStream, CancellationToken cancellationToken)
        {
            List <byte> receiverStdOut = new List <byte>();
            List <byte> receiverStdErr = new List <byte>();

            byte[] buffer = new byte[15];

            while (!cancellationToken.IsCancellationRequested)
            {
                var readResult =
                    await multiplexedStream.ReadOutputAsync(buffer, 0, buffer.Length, cancellationToken);

                if (readResult.Target == MultiplexedStream.TargetStream.StandardError)
                {
                    receiverStdErr.AddRange(buffer.Take(readResult.Count));
                }

                if (readResult.Target != MultiplexedStream.TargetStream.StandardOut)
                {
                    continue;
                }

                int newLineIndex = -1;

                for (int i = 0; i < readResult.Count; ++i)
                {
                    if (buffer[i] == NewLineChar)
                    {
                        newLineIndex = i;
                        break;
                    }
                }

                if (newLineIndex != -1)
                {
                    receiverStdOut.AddRange(buffer.Take(newLineIndex));
                    break;
                }

                receiverStdOut.AddRange(buffer.Take(readResult.Count));
            }

            var result = new ContainerOutput();

            try
            {
                result.StdErr = Encoding.ASCII.GetString(receiverStdErr.ToArray());
            }
            catch (Exception ex)
            {
                this.logger.LogWarning(ex, "Ошибка при чтении stderr");
            }

            result.StdOut = Encoding.ASCII.GetString(receiverStdOut.ToArray());

            return(result);
        }
コード例 #6
0
ファイル: StdinWriter.cs プロジェクト: kkokosa/SharpLab
        public async Task WriteCommandAsync(MultiplexedStream stream, StdinCommand command, CancellationToken cancellationToken)
        {
            var memoryStream = new MemoryStream();

            Serializer.SerializeWithLengthPrefix(memoryStream, command, PrefixStyle.Base128);
            memoryStream.Seek(0, SeekOrigin.Begin);
            await stream.CopyFromAsync(memoryStream, cancellationToken);

            //await stream.WriteAsync(new byte[1024], 0, 1024, cancellationToken);
        }
コード例 #7
0
ファイル: Docker.cs プロジェクト: lie112/ApsimX
        /// <summary>
        /// Read and return container logs as a tuple of (stdout, stderr).
        /// </summary>
        /// <param name="id">Container ID.</param>
        /// <param name="tty">Was the container started with TTY enabled?</param>
        /// <param name="cancelToken">Cancellation token.</param>
        private async Task <(string, string)> GetContainerLogsAsync(string id, bool tty, CancellationToken cancelToken)
        {
            ContainerLogsParameters logParameters = new ContainerLogsParameters()
            {
                ShowStdout = true,
                ShowStderr = true,
                Follow     = false
            };

            using (MultiplexedStream logStream = await client.Containers.GetContainerLogsAsync(id, tty, logParameters, cancelToken))
                return(await logStream.ReadOutputToEndAsync(cancelToken));
        }
コード例 #8
0
        public async Task <string> ReadLineAsync(MultiplexedStream multiplexedStream, CancellationToken cancellationToken)
        {
            List <byte> received = new List <byte>();

            byte[] buffer = new byte[15];

            while (!cancellationToken.IsCancellationRequested)
            {
                var readResult =
                    await multiplexedStream.ReadOutputAsync(buffer, 0, buffer.Length, cancellationToken);

                if (readResult.Target != MultiplexedStream.TargetStream.StandardOut)
                {
                    continue;
                }

                int newLineIndex = -1;

                for (int i = 0; i < readResult.Count; ++i)
                {
                    if (buffer[i] == NewLineChar)
                    {
                        newLineIndex = i;
                        break;
                    }
                }

                if (newLineIndex != -1)
                {
                    received.AddRange(buffer.Take(newLineIndex));
                    break;
                }

                received.AddRange(buffer.Take(readResult.Count));
            }

            return(Encoding.UTF8.GetString(received.ToArray()));
        }
コード例 #9
0
        protected override async Task PostProcess(String pathChanged, MultiplexedStream stream)
        {
            MemoryStream output = new MemoryStream();
            await stream.CopyOutputToAsync(null, output, null, default(CancellationToken));

            output.Position = 0;
            using (StreamReader reader = new StreamReader(output)) {
                String text = await reader.ReadToEndAsync();

                if (text.Contains($"exec: \\\"{m_Shell}\\\": executable file not found in $PATH"))
                {
                    m_Notifier.LogMessage($"Cannot execute {m_Shell} for this container ({m_Notifier.m_Container}) changing for {m_ReplacingShell}");
                    m_Shell       = m_ReplacingShell;
                    m_HandleError = false;
                    await Notify(pathChanged);
                }
                else
                {
                    m_Notifier.LogMessage($"Can execute {m_Shell} for this container ({m_Notifier.m_Container}) disactivating error handling");
                    m_HandleError = false;
                }
            }
        }
コード例 #10
0
ファイル: RconStream.cs プロジェクト: valincius/mc_serverman
 public RconStream(MultiplexedStream stream) =>
 (Stream) = (stream);
コード例 #11
0
ファイル: StdoutReader.cs プロジェクト: kkokosa/SharpLab
        public async Task <ExecutionOutputResult> ReadOutputAsync(
            MultiplexedStream stream,
            byte[] outputBuffer,
            ReadOnlyMemory <byte> outputStartMarker,
            ReadOnlyMemory <byte> outputEndMarker,
            CancellationToken cancellationToken
            )
        {
            var currentIndex     = 0;
            var outputStartIndex = -1;
            var outputEndIndex   = -1;
            var nextStartMarkerIndexToCompare = 0;
            var nextEndMarkerIndexToCompare   = 0;
            var cancelled = false;

            while (outputEndIndex < 0)
            {
                var(read, readCancelled) = await ReadWithCancellationAsync(stream, outputBuffer, currentIndex, outputBuffer.Length - currentIndex, cancellationToken);

                if (readCancelled)
                {
                    cancelled = true;
                    break;
                }

                if (read.EOF)
                {
                    await Task.Delay(10, cancellationToken);

                    continue;
                }

                if (outputStartIndex == -1)
                {
                    var startMarkerEndIndex = GetMarkerEndIndex(
                        outputBuffer, currentIndex, read.Count,
                        outputStartMarker, ref nextStartMarkerIndexToCompare
                        );
                    if (startMarkerEndIndex != -1)
                    {
                        outputStartIndex = startMarkerEndIndex;
                    }
                }

                // cannot be else if -- it might have changed inside previous if
                if (outputStartIndex != -1)
                {
                    var endMarkerEndIndex = GetMarkerEndIndex(
                        outputBuffer, currentIndex, read.Count,
                        outputEndMarker, ref nextEndMarkerIndexToCompare
                        );
                    if (endMarkerEndIndex != -1)
                    {
                        outputEndIndex = endMarkerEndIndex - outputEndMarker.Length;
                    }
                }

                currentIndex += read.Count;
                if (currentIndex >= outputBuffer.Length)
                {
                    break;
                }
            }

            if (outputStartIndex < 0)
            {
                return(new(outputBuffer.AsMemory(0, currentIndex), StartOfOutputNotFound));
            }
            if (cancelled)
            {
                return(new(outputBuffer.AsMemory(outputStartIndex, currentIndex - outputStartIndex), ExecutionTimedOut));
            }
            if (outputEndIndex < 0)
            {
                return(new(outputBuffer.AsMemory(outputStartIndex, currentIndex - outputStartIndex), UnexpectedEndOfOutput));
            }

            return(new(outputBuffer.AsMemory(outputStartIndex, outputEndIndex - outputStartIndex)));
        }
コード例 #12
0
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
        protected virtual async Task PostProcess(String pathChanged, MultiplexedStream stream)
        {
        }
コード例 #13
0
ファイル: StdoutReader.cs プロジェクト: kkokosa/SharpLab
        // Underlying stream does not handle cancellation correctly by default, see
        // https://stackoverflow.com/questions/12421989/networkstream-readasync-with-a-cancellation-token-never-cancels
        private async Task <(ReadResult result, bool cancelled)> ReadWithCancellationAsync(MultiplexedStream stream, byte[] buffer, int index, int count, CancellationToken cancellationToken)
        {
            var cancellationTaskSource = new TaskCompletionSource <object?>();

            using var _ = cancellationToken.Register(() => cancellationTaskSource.SetResult(null));

            var result = await Task.WhenAny(
                stream.ReadOutputAsync(buffer, index, count, cancellationToken),
                cancellationTaskSource.Task
                );

            if (result == cancellationTaskSource.Task)
            {
                return(default, true);
コード例 #14
0
        /// <summary>
        /// Creates a new container and lists it to output.
        /// </summary>
        protected override async Task ProcessRecordAsync()
        {
            foreach (var id in ParameterResolvers.GetImageIds(Image, Id))
            {
                var createResult = await ContainerOperations.CreateContainer(
                    id,
                    this.MemberwiseClone() as CreateContainerCmdlet,
                    DkrClient);

                if (createResult.Warnings != null)
                {
                    foreach (var w in createResult.Warnings)
                    {
                        if (!String.IsNullOrEmpty(w))
                        {
                            WriteWarning(w);
                        }
                    }
                }

                if (!String.IsNullOrEmpty(createResult.ID))
                {
                    MultiplexedStream stream = null;
                    Task streamTask          = null;
                    try
                    {
                        if (!Detach)
                        {
                            var parameters = new ContainerAttachParameters
                            {
                                Stdin  = Input,
                                Stdout = true,
                                Stderr = true,
                                Stream = true
                            };

                            stream = await DkrClient.Containers.AttachContainerAsync(createResult.ID, Terminal, parameters, CmdletCancellationToken);

                            streamTask = stream.CopyToConsoleAsync(Terminal, Input, CmdletCancellationToken);
                        }

                        if (!await DkrClient.Containers.StartContainerAsync(createResult.ID, new ContainerStartParameters()))
                        {
                            throw new ApplicationFailedException("The container has already started.");
                        }

                        if (!Detach)
                        {
                            await streamTask;
                        }
                    }
                    finally
                    {
                        stream?.Dispose();
                    }

                    if (RemoveAutomatically && !Detach)
                    {
                        await DkrClient.Containers.RemoveContainerAsync(createResult.ID,
                                                                        new ContainerRemoveParameters());
                    }
                    else if (PassThru)
                    {
                        WriteObject((await ContainerOperations.GetContainersById(createResult.ID, DkrClient)).Single());
                    }
                }
            }
        }
コード例 #15
0
        public async void ReadStream(MultiplexedStream stream)
        {
            containerStream = stream;
            try
            {
                MatchEvaluator matchEval = new MatchEvaluator(AnsiEscapeHandler);
                while (containerStream != null)
                {
                    var buffer = new byte[1024 * 4];

#if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
                    // unfortunately Stream.ReadAsync waiting for input blocks writing,
                    // so we only peek to see if we have data, than wait for a bit
                    // peek does not work on linux apparently
                    containerStream.Peek(buffer, 1, out var peeked, out var available, out var remaining);

                    if (available == 0)
                    {
                        await Task.Delay(100);

                        continue;
                    }
#endif

                    var result = await containerStream.ReadOutputAsync(buffer, 0, buffer.Length, readCancellationTokenSource.Token);

                    var str = Encoding.UTF8.GetString(buffer, 0, result.Count);
                    str = ansiEscape.Replace(str, matchEval);

                    cleanLog += ansiEscape.Replace(str, string.Empty);

                    int spanStart = 0;
                    while (spanStart < str.Length)
                    {
                        var foundIndex = str.IndexOfAny(new[] { '\u0007', '\u0008' }, spanStart);
                        if (foundIndex == -1)
                        {
                            Append(str.Substring(spanStart));
                            break;
                        }

                        if (spanStart < foundIndex)
                        {
                            Append(str.Substring(spanStart, foundIndex - spanStart));
                        }

                        switch (str[foundIndex])
                        {
                        case '\u0008': Backspace(); break;

                        case '\u0007': OnBell(); break;
                        }

                        spanStart = foundIndex + 1;
                    }
                    if (result.EOF)
                    {
                        break;
                    }
                }
            }
            catch (Exception e)
            {
                Debug.LogException(e);
            }

            containerStream = null;
            WriteLine("Process has ended, press enter key to close tab.");
        }
コード例 #16
0
 public void CloseStream()
 {
     containerStream?.Close();
     containerStream?.Dispose();
     containerStream = null;
 }
コード例 #17
0
 public ActiveContainer(string containerId, MultiplexedStream stream)
 {
     ContainerId = containerId;
     Stream      = stream;
 }