3

I'm trying to use Select-String in PowerShell to look at the results from docker inspect command, but the Context property doesn't seem to be working properly.

As you know, docker inspect returns normal JSON as output, e.g.:

[
    {
        "Id": "c8a5810c62d8dbea11335be561522b4a3df53b9ddcae5531ae06483926c5f992",
        "Created": "2018-07-31T17:16:53.8689464Z",
        "Path": "nginx",
        "Args": [
            "-g",
            "daemon off;"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 13613,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2018-07-31T17:16:54.6460418Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        ...
    },
    ...
]

Running sls (alias for Select-String) without any additional arguments:

enter image description here

And running it with Context:

enter image description here

As you can see, the output is the same, and I don't see the before and after lines in my output

I'm able to use grep to do what I want; e.g.,

docker inspect devtest | grep Mounts -B 5 -A 5

Output of grep:

enter image description here

But I was wondering why Select-String doesn't work.


Update

As @iRon suggested, I even tried saving the output to a file and then use Select-String on the file (sample file):

enter image description here

So, I'm really confused as to what's happening. Because for @iRon it's working properly.


Update 2

I noticed that if I do something like this:

$result = $json | Select-String "Mounts" -Context 5`

then when I look at $result[0].Context.PreContext (and PostContext), they contain the before and after lines in the input, but for some unknown reason, they're not printed to the console

Farzad
  • 1,770
  • 4
  • 26
  • 48
  • 1. You need to export your input file as JSON file and attach to this question 2. This question is not docker related and shall be posted to powershell forum – Gregory Suvalian Jul 30 '18 at 14:55
  • I do not have Docker and grep installed. Can you add (a part of) the input text and the expect output into the question? – iRon Jul 31 '18 at 12:18
  • @iRon I updated the question to include part of the output returned by the `docker inspect` command. As you see it's normal JSON, but I don't want to parse JSON and all that; I just want to use `Select-String` and be able to see the `Context` – Farzad Jul 31 '18 at 17:21
  • Thanks for adding the info but it confuses me as I would expect to find the word `mount` in the `docker inspect` output example, especially knowing you do not want to parse it with a simple cmdlet as [`ConvertFro-Json`](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/convertfrom-json?view=powershell-6) – iRon Jul 31 '18 at 20:53
  • Yes @iRon, that's the point. In theory, I *should* be able to use `ConvertFrom-Json`, but the thing is that I don't know exactly where `Mounts` is in the hierarchy, so I thought `Select-String` would help, but my problem is that the `Context` property doesn't work here! If you check the screenshot I included for `grep`, you can see `Mounts` (I just copy pasted a few lines for brevity and to only show the shape of the output) – Farzad Aug 01 '18 at 02:15

1 Answers1

1

As said, I do not have Docker installed (as I am on Windows 10 Home but I am currently trying to install Dock Toolbox).
Anyways, I think you should be able to exclude docker from your question by splitsing the command:

$Json = docker inspect devtest
$Json | Select-String "Mounts" -Context 5

Investigate the $Json string and build a MCVE question like:
"How do I use Select-String -Context on a raw text file?"

Question:

I have the following raw Json string:

$Json = @'
[
    {
        "Id": "c8a5810c62d8dbea11335be561522b4a3df53b9ddcae5531ae06483926c5f992",
        "Created": "2018-07-31T17:16:53.8689464Z",
        "Path": "nginx",
        "Args": [
            "-g",
            "daemon off;"
        ],
        "Mounts": [
            {
                "Type": "bind",
                "Source": "/tmp/source/target",
                "Destination": "/app",
                "Mode": "ro",
                "RW": false,
                "Propagation": "rprivate"
            }
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 13613,
            "ExitCode": 0,
            "Error": "",
        }
    }
]
'@

If I run $Json | Select-String "Mounts" -Context 5 I do not get the expected results.

Answer

The Select-String cmdlet expects a stream (an array) of lines and not a raw text object separated by Carriage Returns and/or LineFeeds (or whatever your operating system uses for a NewLine).
This means that a line (a single string item in the array) could contain even a NewLine character but is still considered as a single line by the Select-String cmdlet.
In other words, the docker inspect devtest output is concidered as one single line by the Select-String cmdlet

The solution is to split your text into an array of string (lines), String[]:

$Json -Split "[\r\n]+" | Select-String "Mounts" -Context 5

Result:

  "Path": "nginx",
  "Args": [
  "-g",
  "daemon off;"
  ],
> "Mounts": [
  {
  "Type": "bind",
  "Source": "/tmp/source/target",
  "Destination": "/app",
  "Mode": "ro",

Your test.json file works fine as well:

Get-Content .\test.json | Select-String "Mounts" -Context 5

                  "UpperDir": "/var/lib/docker/overlay2/232d9803e4cdb9ec031561cfae7589a43a7fdc06e0517cc3f17417e44d5174fb/diff",
                  "WorkDir": "/var/lib/docker/overlay2/232d9803e4cdb9ec031561cfae7589a43a7fdc06e0517cc3f17417e44d5174fb/work"
              },
              "Name": "overlay2"
          },
>         "Mounts": [],
          "Config": {
              "Hostname": "c8a5810c62d8",
              "Domainname": "",
              "User": "",
              "AttachStdin": false,
iRon
  • 20,463
  • 10
  • 53
  • 79
  • Thank you @iRon for the answer, but I cannot get it to work, I think even with the `Split`, the output is still a single string – Farzad Aug 01 '18 at 12:49
  • I made a mistake. It should probably be `-Split "[\r\n]+"`, I changed it in the answer. (btw. what OS do you use?) – iRon Aug 01 '18 at 13:26
  • Thank you again @iRon, I tried with `"[\r\n]+"`, but still `Context` doesn't work. I'm using Windows 10. There should be something from the `docker` command output. Also, I'm not sure what I'm missing, but I tried to play with your example, and it still doesn't work. I even put it in a file `test.json`, and then I do `$json = cat hello.json` and then `$json -Split "[\r\n]+" | sls Mounts -Context 5`, but no luck! Also, I noticed that if I look at `$json[0]`, `$json[1]` etc., they contain the individual lines, so maybe it's already an array?! :( – Farzad Aug 01 '18 at 16:34
  • (Presuming `test.json` and `hello.json` are both samples), I am a little concerned by the Unix commands (as `Grep` and `Cat`) you refer to. I would use real Windows (PowerShell) commands, e.g. to write the file: `docker inspect devtest | Out-File .\test.json`, to read the file: `$json = .\test.json | get-content`. (note that [`get-content`](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-content?view=powershell-6) returns indeed an array of strings.) I suspect an issue with character coding or NewLines chars. Can you share a sample json file somewhere? – iRon Aug 01 '18 at 17:22
  • Actually, I don't think being an array is an issue. [this is the sample file](https://file.io/y9HR8M), And this is what I do: `docker inspect c8a5810c62d8 | Out-File test.json`, then `$json = Get-Content .\test.json`. After this, when I look at, for example, `$json[24]`, it's showing me `"HostnamePath": ...`, so I think it's already an array of strings. Don't you think so? – Farzad Aug 01 '18 at 17:50
  • Yes, this one works and `Get-Content .\test.json | Select-String "Mounts" -Context 5` works as well (I have added the results to the answer). In other words, I do not see an issue, do I miss something? – iRon Aug 01 '18 at 18:06
  • I have no idea what's happening!!! I'm going to update my question and include a screenshot of the result I get – Farzad Aug 01 '18 at 18:52