"set: illegal option -" on one host but not the other - linux

I've written a sh script in one of my ubuntu VMs which works fine, but when I try to run it in my other VMs, it does not work. Both VMs should be the same. With bash --version both VMs reply with:
GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
With lsb_release -a, both also reply:
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 14.04.3 LTS
Release: 14.04
Codename: trusty
My security_steps.sh script looks like this:
#!/bin/sh
set -e
if ! [ -f svn_up_action.sh ]; then
echo "svn_up_action.sh is missing. Please make sure it is in the same directory as this script."
exit
fi
When I do: sudo sh security_steps.sh, the console errors with:
: not foundeps.sh: 6: security_steps.sh:
security_steps.sh: 7: set: Illegal option -
How can I figure out what's going on with the VM of the non-working shell? I feel like the shells are somehow different. I appreciate your help!

This almost certainly means your file has DOS newlines -- thus, hidden CR characters at the end.
Thus, set -e becomes set -e$'\r' (using bash-specific syntax to represent the CR character), which isn't a valid option.
This also explains the : not found, as a CR will reset the cursor to the beginning of the line, truncating an error message of the form sh: commandname: not found by making the commandname instead an operation that moves the cursor to the beginning of the line.

I had *.sh file throwing me this while running it on Windows (via GitBash).
I've had to change line endings to UNIX/OSX format.

In Windows:
choco install dos2unix
dos2unix file.sh
In Linux:
sudo apt install dos2unix
dos2unix file.sh
dos2unix converts the file to the Unix type.
After doing this, try to run the application again or the file.

If you run into this problem because you are touching your files on a Windows machine, Notepad++ is your friend.
Inspection
View > Show Symbol > Show All Characters
Look for CR LF line endings, rather than LF line endings!
Solving
Search > Replace (Ctrl+H)
Make sure Search Mode is set to Extended
Find \r\n and replace with \n

I got the same Error,
Later I found that these raise because My shell script file moved from a windows machine to Linux machine(there may be a chance of formating or Encoding error).
So I have created the document in Linux machine itself. It solved the issue.
This "May" help few, I am posting this because it worked for me.

You can use the below command, it will remove the hidden CR characters
sed -i 's/\r$//' filename

Related

macos command line params not working at the end

On linux systems when you type a command in a shell like rm * -rf, the order of the * and the -rf doesn't matter. My shell interpret it the same way. Now, on my Mac when I type rm -rf * everything works fine, but if I do rm * -rf an error shows up rm: -rf: No such file or directory
I tried that on a macOS and a linux both with fish and bash shells. Same problems.
Does anyone have any idea why the command interpreter on macOS thinks that -rf at the end of the command is not interpreted as parameters of the command ?
It's not about the shell, it's about the commands.
The parsing of command line arguments is not a feature and responsibility of the shell, but of the actual commands.
In both systems the shell faithfully passes the command line arguments in whatever order they were specified, and then it's up to the implementation of the commands to parse them as they see fit.
In linux, the core utilities are typically of the GNU implementation,
while on osx, the core utilities are typically of the BSD implementation.
The man page of the commands should tell you which implementation it is.
For example the last line of man rm in Linux is something like this:
GNU coreutils 8.21 March 2016 RM(1)
On osx:
BSD January 28, 1999 BSD
Order of the arguments in any shell has historically been relevant in unix.
rm incidentally even has an option -- to stop parsing options (to be able to remove files that start with "-" e.g.)
See rm(1) and getopt(3) man pages
if the shell doesn't respect order of the arguments it is given just what would the result be of this sequence:
$ touch a b
$ mv a b
what file would remain ?

How can I test my Bash script on older versions of Bash?

I'm working on a Bash library and want to ensure I'm supporting as many environments as possible - including old installations of Bash. My development environment is Bash 4.3, but some of my users may well be running much older versions and presently I have no way to confirm or deny that my library will work for them. In particular I'd like to be compatible with OSX (which still ships with Bash 3.2, AFAIK).
I know Bash can run in POSIX-compliant mode; is there a similar setting to disable modern functionality? Or a way to run Bash in some sort of compatibility mode? I'm looking for any technique short of actually finding and booting up old operating systems and testing my library there.
Update
For example, I've avoided using associative arrays since they were introduced in Bash 4, but it's hard to be sure without testing that I'm not accidentally using some other Bash 4+ feature.
Finally coming back to this question, it's pretty easy to just compile (without installing) the bash version(s) you're interested in. Here's how I'm testing Bash 3.2.57:
$ mkdir ~/bash
$ cd ~/bash
$ wget http://ftp.gnu.org/gnu/bash/bash-3.2.57.tar.gz
$ tar xvzf bash-3.2.57.tar.gz
$ cd bash-3.2.57
$ ./configure
$ make
# if `make` fails due to yacc, run `sudo apt-get install byacc`
# No need to run `make install`
$ ./bash -version
GNU bash, version 3.2.57(1)-release (armv7l-unknown-linux-gnu)
Copyright (C) 2007 Free Software Foundation, Inc.
Now you have a bash 3.2.57 binary you can run, without actually "installing" it or modifying your normal environment.
To run a shell script against this version:
$ ./bash your_script.sh
To enter a clean interactive prompt:
$ env -i PATH="$PWD:$PATH" ./bash --noprofile --norc
bash-3.2$ bash -version
GNU bash, version 3.2.57(1)-release (armv7l-unknown-linux-gnu)
Copyright (C) 2007 Free Software Foundation, Inc.
bash-3.2$
Using env -i rather than just calling ./bash directly leaves you with a mostly-empty environment (run env from inside the shell to see what's still set). Updating the PATH allows calls to bash (e.g. bash -version) to invoke the local bash shell, not the system-wide installation (but note this pulls in your whole PATH). Adding --noprofile --norc avoids loading your .bashrc and associated scripts.
If you don't want to pick up any PATH modifications, just execute export PATH="$PWD:$PATH" once inside the subshell instead of as part of the env command.
I have a Docker image (repo) using these installation steps, if that's helpful for folks to reference. I wouldn't necessarily suggest using this image directly, but you're welcome to copy from the Dockerfile/install script. MIT licensed.
Although it's nice to know that it's possible to compile arbitrary versions of bash locally (as discussed in my other answer), these days there's a much simpler option - the official Docker bash images.
To test a script against multiple bash versions is often as simple as:
for v in 3 4 5; do # or whatever versions you're interested in
docker run -v "$PWD:/mnt" "bash:$v" \
bash /mnt/your_script.sh
done
Have a look at shenv: https://github.com/shenv/shenv. Just like rbenv, pyenv, goenv and others, but for shells, it lets you install different versions of Bash among others (zsh, fish, yash, etc.).
(Disclaimer: I'm the one who forked pyenv into shenv!)
You can use Bash own facilities to emulate older version of Bash. Look up "compat" options on shopt.
Mind you, while it does change behavior as described under each compatNN entry in the man page, it does not remove features that are otherwise present on the current version. For example, this doesn't cause any errors:
shopt -s compat31
shopt -s globstar
Even though globstar was only introduced on Bash 4.0.

Bash script syntax error "do"?

#!/bin/sh
for repo in repoA, repoB, repoC;
do
echo Cloning $repo.
done
When I execute this (sh myscript.sh) I get the following:
myscript.sh: line 2: syntax error near unexpected token `$'\r''
'yscript.sh: line 2: `for repo in repoA repoB repoC;
Ideas?
Windows uses two characters at the end of each line: '\r' and '\n'. Unix just uses '\n'. Presumably you're editing this in notepad and running it in cygwin, which is why you're getting this error.
Download the Notepad++ editor, which has an option for unix-style line endings under Edit / EOL Conversion.
You're script was probably written on a windows machine and contains DOS newlines CR LF instead of Unix ones, LF
So you just need to convert the newlines.
You can do that using a variety of tools but my preference is dos2unix
To install it on CentOS, Fedora or RHEL do:
sudo yum install dos2unix
To install dos2unix on Ubuntu or Debian:
sudo apt-get install tofrodos
sudo ln -s /usr/bin/fromdos /usr/bin/dos2unix
Now to actually do the conversion do:
dos2unix your_script.sh
Then run the script
sh your_script.sh
You forgot a semicolon:
#!/bin/sh
for repo in repoA repoB repoC;
do
echo Cloning $repo.
done
Note that repoA, repoB and repoC are being treated as variables in this context.

Any command we can use to convert windows file to unix or mac file?

I don't want to use dos2unix tool. I want to use command in Ubuntu terminal to convert Windows file to Unix file. Is that possible. I have looked through other articles and tried those commands but none working. Anyone can help?
You can use tr to remove carriage returns like this:
tr -d '\r' < WindowsFile > UnixFile
You can use
cat -vet WindowsFile
to see if there are carriage returns in your file and they'll show up as ^M
I want to use command in Ubuntu terminal to convert Windows file to Unix file.
dos2unix path/to/file/to/convert
I don't want to use dos2unix tool.
alias notdos2unix=dos2unix
notdos2unix path/to/file/to/convert
For Ubuntu(and Debian) you can use the tofrodos package.
sudo aptitude install tofrodos
fromdos file.txt # converts the file to UNIX line-endings
todos file.txt # converts the file to Windows line-endings
OSX (being a derivative of UNIX) should have the same line-endings as UNIX.
If you're on Windows, you can find tofrodos binaries here.
If you're on a Mac, you can use the brew package manager and install the tofrodos on OSX.

Linux command to DOS

I have a file include some linux command and I want to run in on windows (DOS command).
The command is:
cat tmp/$id/index.html | sed -e 's/ID/$id/g' > a;mv a tmp/$id/index.html
What is the similar command in MS-DOS?
Thank you!
The problem is that natively there is no equivalent command to sed. You have two options from my point of view. Either create a vb script that does what you want (It will not take 1 line though - more like 10-15 I guess), or use something like GnuWin32 that gives you the option to run unix commands in windows terminal.
You could consider using powershell to do approximately the same thing. It supports cat and mv and you can get a sed like equivalent by using %{_ -replace "expression", "replace"}. Details here http://blogs.msdn.com/b/zainnab/archive/2007/07/09/grep-and-sed-with-powershell.aspx
Or consider using a linux like command prompt like bash which should be available through cygwin
I think this is impossible to do in "bare" command line (as you called DOS command), because cat and sed are separate utilities. If you want to port this script from Linux command shell to windows command line, I would advise you to download and install CygWin
DOS itself does not have support for that. You could try with a port of SED for DOS available here. If you can get Powershell, that's an option. Here's an example of using grep/sed with Powershell.
There are many options.
You can try to install cygwin or download and install Git and use Git-bash or add the bin directory to your PATH so you can run this command on your CMD prompt.
There is no such command(s) for MS-DOS.

Resources