Linux/Ubuntu set: Illegal option -o pipefail
You are running bin/sh
, on Ubuntu it is a symbolic link pointing to /bin/dash
, but pipefail
is a bashism.
Make the script executable:
chmod +x myscript.sh
and then run the script as follows:
sudo ./myscript.sh
Setting pipefail for a single piped command
From the Bash command line you would need to invoke a subshell to avoid pipefail
being set afterwards:
$ (set -o pipefail && command1 | command2 | command3)
This would limit the effect of the pipefail
option to the subshell create by the parentheses (...)
.
A real example:
$ (set -o pipefail && false | true) && echo pipefail inactive || echo pipefail active
pipefail active
If you use an explicit shell call with the -c
option you do not need a subshell, either with bash
or with an sh
alias to bash
:
$ bash -c "set -o pipefail && false | true" && echo pipefail inactive || echo pipefail active
pipefail active
$ sh -c "set -o pipefail && false | true" && echo pipefail inactive || echo pipefail active
pipefail active
Since your sh
does not accept the pipefail
option, I would have to assume that it is either some older or modified version of bash
- or that it is actually some other shell completely.
read fails with set -eou pipefail
The read
command tries to read a single line from standard input. If it fails for any reason -- including hitting the end-of-file before seeing a line terminator -- it exits with a nonzero status. In your case, the -d ''
option tells read
to look for an ASCII null character as the line terminator, and since the here-document doesn't have one it reads until it hits EOF... and then exits with an error status.
read
's behavior may be a bit counterintuitive here. It read something successfully, and set the variable (payload
) just fine; but since it hit EOF it's required by the POSIX standard to return an error. The exact same thing happens when reading a text file line-by-line, and the last line isn't terminated.
Normally this wouldn't be a big deal, but the -e
option to set
makes the shell exit if any simple command exits with a nonzero (error) status (with lots of messy exceptions that aren't relevant here). When read
does that, the script exits on the spot.
So, there are a few possible solutions. You could just not use set -e
, you could put set +e
just before the read
command (and maybe set -e
again afterward), or you could make it a compound command that'll succeed, like this:
read -rd '' payload << EOF || true
...
(Here, the ||
means if the first command fails it'll run the second, and true
always succeeds, so the compound command is considered to succeed.)
Bash script - check how many times public IP changes
while true
PREV_IP=00
do
is the reason you are seeing ip each loop. It's the same as while true; PREV_IP=00; do
. The exit status of true; PREV_IP=00
is the exit status of last command - the exit status of assignment is 0 (success) - so the loop will always execute. But PREV_IP
will be reset to 00
each loop... This is a typo and you meant to set prev_ip
once, before the loop starts.
"$(date)"
will try execute the output of date
command, as a next command. So it will print:
$ "$(date)"
bash: sob, 20 mar 2021, 10:57:02 CET: command not found
And finally, to silence curl
, read man curl
first and then find out about -s
. I use -sS
so errors are also visible.
Do not use uppercase variables in your scripts. Prefer lower case variables. Check you scripts with http://shellcheck.net . Quote variable expansions.
I would sleep each loop. Your script could look like this:
#!/bin/bash
prev=""
while true; do
cur=$(curl -sS https://ipinfo.io/ip)
if [ "$prev" != "$cur" ]; then
prev="$cur"
echo "$(date) $cur"
fi
sleep 1
done
that I want the output to direct to a file instead of outputting it into the terminal.
Then research how redirection works in shell and how to use it. The simplest would be to redirect echo output.
echo "$(date) $cur" >> "a_file.txt"
The interval is currently set to 1 second for test purposes. This will change to a higher interval in the final product.
You are still limited with the time it takes to connect to https://ipinfo.io/ip
. And from ipinfo.io documentation:
Free usage of our API is limited to 50,000 API requests per month.
And finally, I wrote a script where I tried to use many public services as I found ,get_ip_external for getting external ip address. You may take multiple public services for getting ipv4 address and choose a random/round-robin one so that rate-limiting don't kick that fast.
Start up script fails with error -e: invalid option , what is missing?
In your secondary script, you have this line at the end :
exec "$@"
It is very likely (well, mostly certain) that positional parameters contain -e
as an argument. Where could that come from, you may ask?
Your secondary script is sourced by this line in the primary script :
. $init
Sourced scripts execute in the context of the parent, so positional parameters are not replaced (unless you specify arguments after the name of the file you are sourcing). If $1
in your parent script contains -e
, your sourced script will see that. It is possible your main script is receiving an argument, or one of your secondary scripts changes arguments. It is a bit of a problem executing all these scripts in the same context, there can be variables and positional parameters leaking.
There is another issue I am seeing : your secondary script ends with an exec
command, which replaces the current process with the command provided in argument (except in the specific cases where exec
is used to manipulate file descriptors). Therefore, I would expect this secondary script to never return to the main script, and because of the secondary script being sourced, your primary script actually never finishing.
Related Topics
Syntax Error Near Unexpected Token ' - Bash
Why Can't I Access Xampp's PHPmyadmin on Localhost? Access Is Forbidden
Problems Installing R on Linux Centos 6.2
Linux: Run Cron Job in Foreground
Elasticsearch Process Memory Locking Failed
Get Time in Milliseconds Without an Installing an Extra Package
Multiple Option Arguments Using Getopts (Bash)
Does Madvise(_, _, Madv_Dontneed) Instruct the Os to Lazily Write to Disk
Fork() Failing with Out of Memory Error
Print on Terminal and into File Simultaneously
Service Doesn't Support Chkconfig
Get Rid of "Gcc - /Usr/Bin/Ld: Warning Lib Not Found"
Running Docker on Ubuntu: Mounted Host Volume Is Not Writable from Container
Docker Not Responding to Ctrl+C in Terminal
Dynamic Loading and Weak Symbol Resolution
What Is the Most Efficient and Elegant Way Develop/Debug Linux Kernel
How to Add a Footer to the Bottom of Each Page of a Postscript or PDF File in Linux