check.sh: 2: [[: not found means a script that uses bash's
[[ ]] test was run by sh, which on Ubuntu is dash, and dash has
no [[. Run it with bash check.sh, or change the test to the
single-bracket form [ -n "$1" ] that sh understands.
The dangerous part: the script did not stop. It skipped the if body, printed
done and exited with 0, so nothing in the exit code tells you the test never
ran.
The error
docker exec fix10-lc-u3 bash -c 'cat /root/check.sh; cat /root/check2.sh; ls -l /bin/sh'
#!/bin/bash
if [[ -n "$1" ]]; then
echo "argument: $1"
fi
echo "done"
...
docker exec fix10-lc-u3 bash -c 'cd /root; sh check.sh Maria 2>&1; echo exit=$?'
check.sh: 2: [[: not found
done
exit=0
The 2 in check.sh: 2: is the line number of the
if.
Why it happens
The first line says #!/bin/bash, but sh check.sh asks sh to
read the file, so the first line is only a comment. In the ubuntu:24.04
image /bin/sh is dash:
docker exec fix10-lc-u3 bash -c 'cat /root/check.sh; cat /root/check2.sh; ls -l /bin/sh'
...
lrwxrwxrwx 1 root root 4 Mar 31 2024 /bin/sh -> dash
Dash reported [[ as a command it could not find. The if took
that failure as false and went on to the next line. Run without an argument, the script
printed the same error, so the message tells you about the shell, not about the value
you passed:
docker exec fix10-lc-u3 bash -c 'cd /root; sh check.sh 2>&1; echo exit=$?'
check.sh: 2: [[: not found
done
exit=0
The fix
Run the script with the shell it was written for:
docker exec fix10-lc-u3 bash -c 'cd /root; bash check.sh Maria 2>&1; echo exit=$?'
argument: Maria
done
exit=0
Or, when the script must run under sh, use the single bracket. The same test,
written as [ -n "$1" ] in check2.sh, worked under sh:
docker exec fix10-lc-u3 bash -c 'cat /root/check.sh; cat /root/check2.sh; ls -l /bin/sh'
...
#!/bin/bash
if [ -n "$1" ]; then
echo "argument: $1"
fi
echo "done"
...
docker exec fix10-lc-u3 bash -c 'cd /root; sh check2.sh Maria 2>&1; echo exit=$?'
argument: Maria
done
exit=0
With single brackets, quote the variable: "$1", not $1. The
unquoted form breaks on an empty value and on a value with a space; those two cases are
reproduced in
[: =: unary operator expected
and [: too many arguments,
each with its own capture and fix.
How it was reproduced
The capture was made in a container started with
docker run -d --name fix10-lc-u3 ubuntu:24.04 sleep infinity (Ubuntu 24.04.5
LTS, bash 5.2.21, /bin/sh linked to dash) on Docker Engine 29.9.3. The two
five-line scripts were copied in with
docker cp l3\check.sh fix10-lc-u3:/root/check.sh and the same for
check2.sh. Every command was sent from Windows PowerShell 5.1 as shown,
with the bash -c text in single quotes so it reached the container
unchanged. The container name is the test's own; Maria is a
sample value.
Frequently asked
- What does [[: not found mean?
- A bash script was run by sh, which on Ubuntu is dash and has no [[ test. In the test sh check.sh printed check.sh: 2: [[: not found.
- How do I fix [[: not found in a shell script?
- Run it with bash script.sh, or rewrite the test with single brackets such as [ -n "$1" ]. Both printed argument: Maria in the test.
- Why does my script continue after [[: not found?
- The failed test counts as false, so the if body is skipped. In the test the script printed done and exited with 0.
More decoded errors in the Fixes category. The same shell mix-up gives /bin/sh: 1: source: not found.