Shell script running different on MacOS and Linux - bash

I'm trying to run my shell script on Linux (Ubuntu).
It's running correctly on MacOS, but on Ubuntu it doesn't.
#!/usr/bin/env bash
while true
do
node Client/request -t 10.9.2.4 -p 4400 --flood
done
Ubuntu output this error for running: sh myScript.sh:
Syntax error: end of file unexpected (expecting "do")
Why is there any difference between them, since both of them are running by Bash? How can I avoid future errors caused by their differences?
I tried cat yourscript.sh | tr -d '\r' >> yournewscript.sh as related question was suggested to do, and also while [ true ].
The command hexdump -C util/runner.sh result is:
00000000 23 21 2f 75 73 72 2f 62 69 6e 2f 65 6e 76 20 62 |#!/usr/bin/env b|
00000010 61 73 68 0d 0a 0d 0a 77 68 69 6c 65 20 5b 20 74 |ash....while [ t|
00000020 72 75 65 20 5d 0d 0a 64 6f 0d 0a 20 20 20 6e 6f |rue ]..do.. no|
00000030 64 65 20 43 6c 69 65 6e 74 2f 72 65 71 75 65 73 |de Client/reques|
00000040 74 20 2d 74 20 31 39 32 2e 31 36 38 2e 30 2e 34 |t -t 192.168.0.4|
00000050 31 20 2d 70 20 34 34 30 30 20 2d 2d 66 6c 6f 6f |1 -p 4400 --floo|
00000060 64 0d 0a 64 6f 6e 65 0d 0a |d..done..|
00000069

The shebang #! line at the top of your file tells that this is a bash script. But then you run your script with sh myScript.sh, therefore using the sh shell.
The sh shell is not the same as the bash shell in Ubuntu, as explained here.
To avoid this problem in the future, you should call shell scripts using the shebang line. And also make sure to prefer bash over sh, because the bash shell is more convenient and standardized (IMHO). In order for the script to be directly callable, you have to set the executable flag, like this:
chmod +x yournewscript.sh
This has to be done only once (it's not necessary to do this on every call.)
Then you can just call the script directly:
./yournewscript.sh
and it will be interpreted by whatever command is present in the first line of the script.

Related

SSH output redirection to file does overwriting instead of appending

I am doing some tasks locally and save debug info to a log file. Then I try to do some other tasks remotely via SSH, and attempt to save the output into the same local file. SSH's output overwrites my log file from the beginning for some reason. For example:
root#localhost:~# echo "The quick brown fox jumps over the lazy dog. 1234567890" 1>"test.log";
root#localhost:~# cat "test.log";
The quick brown fox jumps over the lazy dog. 1234567890
root#localhost:~# echo "echo hello_world" | ssh root#192.168.1.2 "sh -s" 1>>"test.log";
root#localhost:~# cat "test.log";
hello_world
own fox jumps over the lazy dog. 1234567890
What should I do to make it append correctly?
P.S: hexdump -C "test.log"
00000000 68 65 6c 6c 6f 5f 77 6f 72 6c 64 0a 6f 77 6e 20 |hello_world.own |
00000010 66 6f 78 20 6a 75 6d 70 73 20 6f 76 65 72 20 74 |fox jumps over t|
00000020 68 65 20 6c 61 7a 79 20 64 6f 67 2e 20 31 32 33 |he lazy dog. 123|
00000030 34 35 36 37 38 39 30 0a |4567890.|
00000038

Unable to start haproxy 2.4 - Missing LF on last line?

Basically the title. I'm working on upgrading our existing haproxy from 1.5 to the latest version. Because of that, I'm setting up a test case to ensure our old setup can work on it. However, when I try to run it, I get the following error:
[NOTICE] (28948) : haproxy version is 2.4.1-1ce7d49
[NOTICE] (28948) : path to executable is /home/user/test/usr/local/sbin/haproxy
[ALERT] (28948) : parsing [test.cfg:22]: Missing LF on last line, file might have been truncated at position 68.
[ALERT] (28948) : Error(s) found in configuration file : test.cfg
[ALERT] (28948) : Fatal errors found in configuration.
I've tried looking it up, but I cannot find anything on the error. I've already checked my config file, and it is using the correct Unix format. Also, my test config works for the older version of HAProxy.
global
stats timeout 30s
user root
group root
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
frontend http_front
bind *:9090
default_backend http_back
backend http_back
balance roundrobin
server test.server.com 127.0.0.1:8000
In addition, I did the following to install haproxy:
tar xvf haproxy-2.4.1.tar.gz
cd haproxy-2.4.1
#vi to Makefile and set PREFIX to PREFIX = /home/user/test/usr/local
make TARGET=linux-glibc
make install
Is there anything that sticks out regarding my config file? Or did I miss something in the installation process?
Most likely you truncated your config file somehow. It looks ok.
I wasn't testing it on 2.4, but i found reference to it: https://www.mail-archive.com/haproxy#formilux.org/msg37698.html and was able to reproduce it on 2.2 (it was warning in 2.2, became error in 2.3 as described by haproxy message) with this simple config:
defaults
timeout connect 5000
timeout client 50000
timeout server 50000
frontend http_front
bind *:80
mode http
http-request deny
This config is valid:
# haproxy -c -f test.conf
Configuration file is valid
Now i will truncate it by one byte to reproduce it:
# wc -c test.conf
149 test.conf
# dd if=test.conf of=test2.conf bs=1 count=148
148+0 records in
148+0 records out
148 bytes copied, 0.00267937 s, 55.2 kB/s
# hexdump -C test.conf
00000000 64 65 66 61 75 6c 74 73 0a 20 20 20 74 69 6d 65 |defaults. time|
00000010 6f 75 74 20 63 6f 6e 6e 65 63 74 20 35 30 30 30 |out connect 5000|
00000020 0a 20 20 20 74 69 6d 65 6f 75 74 20 63 6c 69 65 |. timeout clie|
00000030 6e 74 20 35 30 30 30 30 0a 20 20 20 74 69 6d 65 |nt 50000. time|
00000040 6f 75 74 20 73 65 72 76 65 72 20 35 30 30 30 30 |out server 50000|
00000050 0a 0a 66 72 6f 6e 74 65 6e 64 20 68 74 74 70 5f |..frontend http_|
00000060 66 72 6f 6e 74 0a 20 20 20 62 69 6e 64 20 2a 3a |front. bind *:|
00000070 38 30 0a 20 20 20 6d 6f 64 65 20 68 74 74 70 0a |80. mode http.|
00000080 20 20 20 68 74 74 70 2d 72 65 71 75 65 73 74 20 | http-request |
00000090 64 65 6e 79 0a |deny.|
00000095
# hexdump -C test2.conf
00000000 64 65 66 61 75 6c 74 73 0a 20 20 20 74 69 6d 65 |defaults. time|
00000010 6f 75 74 20 63 6f 6e 6e 65 63 74 20 35 30 30 30 |out connect 5000|
00000020 0a 20 20 20 74 69 6d 65 6f 75 74 20 63 6c 69 65 |. timeout clie|
00000030 6e 74 20 35 30 30 30 30 0a 20 20 20 74 69 6d 65 |nt 50000. time|
00000040 6f 75 74 20 73 65 72 76 65 72 20 35 30 30 30 30 |out server 50000|
00000050 0a 0a 66 72 6f 6e 74 65 6e 64 20 68 74 74 70 5f |..frontend http_|
00000060 66 72 6f 6e 74 0a 20 20 20 62 69 6e 64 20 2a 3a |front. bind *:|
00000070 38 30 0a 20 20 20 6d 6f 64 65 20 68 74 74 70 0a |80. mode http.|
00000080 20 20 20 68 74 74 70 2d 72 65 71 75 65 73 74 20 | http-request |
00000090 64 65 6e 79 |deny|
00000094
# haproxy -c -f test2.conf
[WARNING] 193/184514 (10725) : parsing [test2.conf:9]: Missing LF on last line, file might have been truncated at position 21. This will become a hard error in HAProxy 2.3.
Warnings were found.
Configuration file is valid
Note the missing 0a at the end. Check your config with hexdump -C
I had the same issue and I tried using Editor. but, it didn't work.
I was able to solve this issue by adding a new line.
I used the echo command and it worked.
echo "" >> /etc/hapee-2.2/hapee-lb.cfg
I had the exact same issue using Rancher when deploying Bitnami HAproxy. I quickly found that the constructor was addinng |- block chomping indicator removing the '0a' at the end. I had to edit the file in yaml format making sure to remove this indicator.
example:
config: |-
defalts
timeout.....
frontend http
bind *:8080
mode http
timeout client 10s
use_backend all
backend all
mode http
server s0 nodeapp0:3000
server s1 nodeapp1:3001
NOTE: Use some newlines (using enter) in your config file. here is my simple cfg file, I used enter keys to deal with the error.
Working Solution:
I faced this issue when running HAproxy on Windows Docker.
After turning on Show All Characters in notepad ++, I could see that the last line was missing new line control character. (On windows both CRLF and LF works fine)
Based on other answers in this thread, proceeded to add a new line by simply hitting enter key after the last character in the config file.
But noticed same error.
parsing [/usr/local/etc/haproxy/haproxy.cfg:28]: Missing LF on last line, file might have been truncated at position 3. Missing LF on last line, file might have been truncated at position 3.
After some trial and error, I got it to work with below changes.
Ensure that the last character of the config file is either CRLF or LF. If there are additional spaces, then remove those (in my case notepad++ added two spaces for auto indentation which was causing the issue even after adding a new line).

How can I remove non-breaking spaces from a text file in bash?

I have a csv file with text and numbers.
If a number is bigger than 1000, formatted like this: 1 000,
so it has a space as thousand separator, but it is not space. I tried to sed it, and it worked where real space was, but not in this format.
It is also not TAB, I removed all the TABs with "expand -t 1".
The following is a line that demonstrates the issue:
x17_Provident_GDN_REMARKETING_provident.hu_listák;Display_Hálózat;Szeged;2021-03-09;Kedd;Mobil;HUF;1 736;9;130.83;0.00
In penultimate row, in column 8: 1 736
is the problem.
And running this: grep -E -m 1 -e '[;]1[^;]+736[;]' <yourfile.csv | hexdump -C
gives:
00000000 78 31 37 5f 50 72 6f 76 69 64 65 6e 74 5f 47 44 |x17_Provident_GD|
00000010 4e 5f 52 45 4d 41 52 4b 45 54 49 4e 47 5f 70 72 |N_REMARKETING_pr|
00000020 6f 76 69 64 65 6e 74 2e 68 75 5f 6c 69 73 74 c3 |ovident.hu_list.|
00000030 a1 6b 3b 44 69 73 70 6c 61 79 5f 48 c3 a1 6c c3 |.k;Display_H..l.|
00000040 b3 7a 61 74 3b 53 7a 65 67 65 64 3b 32 30 32 31 |.zat;Szeged;2021|
00000050 2d 30 33 2d 30 39 3b 4b 65 64 64 3b 4d 6f 62 69 |-03-09;Kedd;Mobi|
00000060 6c 3b 48 55 46 3b 31 c2 a0 37 33 36 3b 39 3b 31 |l;HUF;1..736;9;1|
00000070 33 30 2e 38 33 3b 30 2e 30 30 0a |30.83;0.00.|
0000007b
It's a 2 byte, UTF-8 encoded non breaking space - c2 a0.
You can use perl to safely remove it.
perl -pe 's/\xc2\xa0//g' dirty.csv > clean.csv
After we know it is No break space, I simply sed it on mac with entry method:
opt+space
cat test4.csv | sed 's/ //g'
Similar to perl, you can use GNU sed with LC_ALL=C:
LC_ALL=C sed 's/\xc2\xa0//g'

Remove ^M at end of each line in shell script [duplicate]

This question already has answers here:
How to convert DOS/Windows newline (CRLF) to Unix newline (LF)
(23 answers)
Are shell scripts sensitive to encoding and line endings?
(14 answers)
Closed 5 years ago.
I have this code but doesn't work.
line="20170425"
anycopia=${line:0:4}
mescopia=${line:4:2}
diacopia=${line:6:2}
echo $anycopia
echo $mescopia
echo $diacopia
DATE=$(date +%Y%m%d)
any=${DATE:0:4}
mes=${DATE:4:2}
dia=${DATE:6:2}
echo $any
echo $mes
echo $dia
if [ $anycopia == $any ]; then
echo "equals"
else
echo "not equals"
fi
Error:
syntax error near unexpected token fi
I've tried changing "then" but it doesn't matter, just like this:
if [ $anycopia == $any ]
then
echo "equals"
else
echo "not equals"
fi
And same error going on all over the time.
PD: Other answers in Stack Overflow with same question didn't work for me.
Edit:
I did this command:
hexdump -C script.sh
This is the output:
00000000 6c 69 6e 65 3d 22 32 30 31 37 30 34 32 35 22 0d |line="20170425".|
00000010 0a 61 6e 79 63 6f 70 69 61 3d 24 7b 6c 69 6e 65 |.anycopia=${line|
00000020 3a 30 3a 34 7d 0d 0a 6d 65 73 63 6f 70 69 61 3d |:0:4}..mescopia=|
00000030 24 7b 6c 69 6e 65 3a 34 3a 32 7d 0d 0a 64 69 61 |${line:4:2}..dia|
00000040 63 6f 70 69 61 3d 24 7b 6c 69 6e 65 3a 36 3a 32 |copia=${line:6:2|
00000050 7d 0d 0a 65 63 68 6f 20 24 61 6e 79 63 6f 70 69 |}..echo $anycopi|
00000060 61 0d 0a 65 63 68 6f 20 24 6d 65 73 63 6f 70 69 |a..echo $mescopi|
00000070 61 0d 0a 65 63 68 6f 20 24 64 69 61 63 6f 70 69 |a..echo $diacopi|
00000080 61 0d 0a 44 41 54 45 3d 24 28 64 61 74 65 20 2b |a..DATE=$(date +|
00000090 25 59 25 6d 25 64 29 0d 0a 61 6e 79 3d 24 7b 44 |%Y%m%d)..any=${D|
000000a0 41 54 45 3a 30 3a 34 7d 0d 0a 6d 65 73 3d 24 7b |ATE:0:4}..mes=${|
000000b0 44 41 54 45 3a 34 3a 32 7d 0d 0a 64 69 61 3d 24 |DATE:4:2}..dia=$|
000000c0 7b 44 41 54 45 3a 36 3a 32 7d 0d 0a 65 63 68 6f |{DATE:6:2}..echo|
000000d0 20 24 61 6e 79 0d 0a 65 63 68 6f 20 24 6d 65 73 | $any..echo $mes|
000000e0 0d 0a 65 63 68 6f 20 24 64 69 61 0d 0a 69 66 20 |..echo $dia..if |
000000f0 5b 20 24 61 6e 79 63 6f 70 69 61 20 3d 3d 20 24 |[ $anycopia == $|
00000100 61 6e 79 20 5d 3b 20 74 68 65 6e 0d 0a 20 20 20 |any ]; then.. |
00000110 20 65 63 68 6f 20 22 68 6f 6c 61 22 0d 0a 65 6c | echo "hola"..el|
00000120 73 65 0d 0a 20 20 20 20 65 63 68 6f 20 22 61 64 |se.. echo "ad|
00000130 65 75 22 0d 0a 66 69 0d 0a |eu"..fi..|
00000139
PDD: I'm running this with Bash on Ubuntu on Windows.
Edit2:
user#DESKTOP-UO9KRO4:/mnt/d$ cat -v script.sh
line="20170425"^M
anycopia=${line:0:4}^M
mescopia=${line:4:2}^M
diacopia=${line:6:2}^M
echo $anycopia^M
echo $mescopia^M
echo $diacopia^M
DATE=$(date +%Y%m%d)^M
any=${DATE:0:4}^M
mes=${DATE:4:2}^M
dia=${DATE:6:2}^M
echo $any^M
echo $mes^M
echo $dia^M
if [ $anycopia == $any ]; then^M
echo "hola"^M
else^M
echo "adeu"^M
fi^M
^M is a carriage return, and is commonly seen when files are copied from Windows. Run dos2unix to clean up those meta-characters.
dos2unix script.sh
Also as a safe coding practice,
Always double-quote your variables to not let them split when they contains spaces or any shell meta characters
Define a proper she-bang i.e. the interpreter using which the script should run. (Most cases if bash is available #!/usr/bin/env bash or #!/bin/bash)

tcsh if/then statement gives error

I'm trying to do a simple tcsh script to look for a folder, then navigate to it if it exists. The statement evaluates properly, but if it evaluates false, I get an error "then: then/endif not found". If it evaluates true, no problem. Where am I going wrong?
#!/bin/tcsh
set icmanagedir = ""
set workspace = `find -maxdepth 1 -name "*$user*" | sort -r | head -n1`
if ($icmanagedir != "" && $workspace != "") then
setenv WORKSPACE_DIR `readlink -f $workspace`
echo "Navigating to workspace" $WORKSPACE_DIR
cd $WORKSPACE_DIR
endif
($icmanagedir is initialized elswehere, but I get the error regardless of which variable is empty)
The problem is that tcsh needs to have every line end in a newline, including the last line; it uses the newline as the "line termination character", and if it's missing it errors out.
You can use a hex editor/viewer to check if the file ends with a newline:
$ hexdump -C x.tcsh i:arch:21:49
00000000 69 66 20 28 22 78 22 20 3d 20 22 78 22 29 20 74 |if ("x" = "x") t|
00000010 68 65 6e 0a 09 65 63 68 6f 20 78 0a 65 6e 64 69 |hen..echo x.endi|
00000020 66 |f|
Here the last character if f (0x66), not a newline. A correct file has 0x0a as the last character (represented by a .):
$ hexdump -C x.tcsh
00000000 69 66 20 28 22 78 22 20 3d 20 22 78 22 29 20 74 |if ("x" = "x") t|
00000010 68 65 6e 0a 09 65 63 68 6f 20 78 0a 65 6e 64 69 |hen..echo x.endi|
00000020 66 0a |f.|
Ending the last line in a file with a newline is a common UNIX idiom, and some shell tools expect this. See What's the point in adding a new line to the end of a file? for some more info on this.
Most UNIX editors (such as Vim, Nano, Emacs, etc.) should do this by default, but some editors or IDEs don't do this by default, but almost all editors have a setting through which this can be enabled.
The best solution is to enable this setting in your editor. If you can't do this then adding a blank line at the end also solves your problem.

Resources