0

So I have the following script:

#!/bin/bash
docker run -itd -p 8888:8888 --name notebook --mount type=bind,source="$(pwd)",target=/home/jovyan/work jupyter/datascience-notebook:latest
sleep 10s
link=$(docker logs --until=5s notebook | grep -o -m 1 'http://127.0.0.1:[0-9]*/lab?token=[0-9a-z]*')
var=$(date)

echo $var
echo $link

and when I run it with bash startup.sh it does not print out link variable while it does print var. The crazy thing is if I run these commands individually on my terminal it does set link (which is how I wrote the script in the first place). Also that 10 second sleep is more than enough for the docker logs to be available.

Am I missing something here? is there something special about docker that's causing this? I'm so confused.

Wildhammer
  • 2,017
  • 1
  • 27
  • 33
  • Instead of assuming something this fundamental is broken in bash itself, start by checking your assumptions. Easiest way to do that is to add some `tee`s to your pipelines. – Charles Duffy Apr 27 '22 at 13:50
  • 1
    Also, note that `echo $var` is innately, fundamentally broken. It is [**absolutely not** guaranteed to give you the contents of the variable `var`](https://stackoverflow.com/questions/29378566/i-just-assigned-a-variable-but-echo-variable-shows-something-else). Use `declare -p var` or `printf 'var=%q\n' "$var"` if you want output that provides a solid understanding of values with hidden characters, glob expressions, etc. – Charles Duffy Apr 27 '22 at 13:51
  • ...but going back to the `tee` suggestion: `link=$(docker logs --until=5s notebook | tee docker-logs-out | grep ... | tee docker-logs-filtered)`, then look at your `docker-logs-out` and `docker-logs-filtered` files. – Charles Duffy Apr 27 '22 at 13:52
  • 1
    Also, `bash -x yourscript` is always a good place to start to get trace logs showing the commands that are being actually executed by the script. – Charles Duffy Apr 27 '22 at 13:55
  • Another thing you might consider is to ditch the `docker logs | grep` pattern in place of a `while IFS= read -r line; do ...; done < <(docker logs)` type pattern; then your bash script can do all its monitoring in the `...`, and you can set more nuanced timeouts (f/e, telling `read` itself to time out after 5 seconds _between lines_ instead of having a timeout that's completely fixed), and you can more easily log status to the terminal (`echo "$line">&2`) to avoid needing to guess at what's going on. – Charles Duffy Apr 27 '22 at 13:59
  • Anyhow -- beyond that I can't really suggest much; nobody but you has the specific Docker instance you're experiencing this problem with, whereas a question with a [mre] would contain code anyone could run to see the problem themselves and test proposed solutions. – Charles Duffy Apr 27 '22 at 14:09
  • 1
    One note, though -- I'm a bit surprised your `grep` command works when you run it by hand on the command line. `?` is grep syntax (it means "zero or one of the prior thing"), it doesn't match itself. If you want to match a `?`, use `[?]` (I suggest `[?]` instead of `\?` because backslashes' meaning is more contextually-variant; creating a character class is more reliable). – Charles Duffy Apr 27 '22 at 14:09
  • I will try them thanks. The docker image is public though anyone should be able to run the script. – Wildhammer Apr 27 '22 at 14:25
  • 1
    Try to cut your problem in smaller pieces: Run `docker logs --until=5s notebook > mylogs.txt`, examine/edit the `mylogs.txt` and run `grep -o -m 1 'http://127.0.0.1:[0-9]*/lab?token=[0-9a-z]*' mylogs.txt`. When the `grep` works, capture in `link=$(grep ...)`. After these steps you should have a more precise clue what is going wrong. – Walter A Apr 27 '22 at 14:51

1 Answers1

0

So turns out the problem was that I wasn't waiting enough. After further debugging (shout out to Charles and Walter for their hints) I was able to fix it.

#!/bin/bash
docker run -itd -p 8888:8888 --name notebook --mount type=bind,source="$(pwd)",target=/home/jovyan/work jupyter/datascience-notebook:latest

while true; do
  link=$(docker logs --until=5s notebook | grep -o -m 1 'http://127.0.0.1:[0-9]*/lab?token=[0-9a-z]*')
  [ -z "$link" ] || break
  sleep 1
done

Wildhammer
  • 2,017
  • 1
  • 27
  • 33