Bash script: Turn on errors? - bash

After designing a simple shell/bash based backup script on my Ubuntu engine and making it work, I've uploaded it to my Debian server, which outputs a number of errors while executing it.
What can I do to turn on "error handling" in my Ubuntu machine to make it easier to debug?

ssh into the server
run the script by hand with either -v or -x or both
try to duplicate the user, group, and environment of the error run in your terminal window If necessary, run the program with something like "su -c 'sh -v script' otheruser
You might also want to pipe the result of the bad command, particularly if run by cron(8), into /bin/logger, perhaps something like:
sh -v -x badscript 2>&1 | /bin/logger -t badscript
and then go look at /var/log/messages.

Bash lets you turn on debugging selectively, or completely with the set command. Here is a good reference on how to debug bash scripts.
The command set -x will turn on debugging anywhere in your script. Likewise, set +x will turn it off again. This is useful if you only want to see debug output from parts of your script.

Change your shebang line to include the trace option:
#!/bin/bash -x
You can also have Bash scan the file for errors without running it:
$ bash -n scriptname

Related

How to launch WSL as if I've logged in?

I have a WSL Ubuntu distro that I've set up so that when I login 4 services start working, including a web API that I can test via Swagger to verify it is up and working.
I'm at the point where what I want to do now is start WSL via a script - that is, launch my distro, have all of the services start, and do it from Python. The problem is I cannot even figure out the correct syntax to get WSL to start from PowerShell in a manner where my services start.
Side note: "services" != systemctl (or similar) calls, but just executing bash CLI commands from either my .bashrc or .profile at login.
I've put the commands to execute in .profile & .bashrc. I've configured it both for root execution and non-root user execution. I've taken the commands out of those 2 files and put it into a script in the Windows file system that I pass in on the start of wsl. And I've put that shell script in the WSL file system as well. Nothing seems to work, and sometimes the distro starts and then stops after about 30 seconds.
Some of the PS CLI commands I've tried:
Start-Job -ScriptBlock{ wsl -d distro -u root }
Start-Job -ScriptBlock{ wsl -d distro -u root 'bash -i -l -c /root/bin/start.sh'
Start-Job -ScriptBlock{ wsl -d distro -u root 'bash -i -l -c .\start.sh'
wsl -d distro -u root -- bash -i -l -c /root/bin/start.sh
wsl -d distro -u root -- bash -i -l -c .\start.sh
wsl -d distro -u root -- /root/bin/start.sh
Permutations of the above that I've tried: replace root with my default login, and turning all of the Start-Job bash options into a comma-separated list of single-quoted strings (Ex: 'bash', '-i', '-l', ... ). Nothing I launch from the CLI will allow me access to the web API that is supposed to be hosted on my distro.
Any advice on what to try next?
Not necessarily an answer here as much as troubleshooting tips which will hopefully lead to an answer:
First, most of the forms that you are using seem to be correct. The only ones that absolutely shouldn't work are those that attempt to run the script from the Windows filesystem.
Make sure that you have a shebang line starting your script. I'm assuming you do, but other readers may come across this as well. For the moment, try this form:
#!/usr/bin/env -S bash -li
That's going to have the same effect as the bash -li you tried -- It will source both both interactive startup files such as ~/.bashrc as well as login profiles such as ~/.bash_profile (and /etc/profile.d/*, etc.).
Note that preferably, you won't need the -li. Best practice would be to move anything necessary for the services over from the startup scripts to your start.sh script, and avoid parsing the profile and rc. I need to go update some of my answers, since I just realized I've been guilty of giving some potentially bad advice ...
Specifically, though, I'm wondering if your interactive Bash config has something truly, well, "interactive" in it that might be preventing the automatic running of the script itself. Again, best practice would be for ~/.bashrc to only hold configuration that is needed for interactive shell sessions.
Make sure the script is set as executable (chmod +x start.sh). Again, I'm assuming this is the case for you.
With a shebang line and an executable script, use something like:
wsl -d distro -u root -e /root/bin/start.sh
The -e tells WSL to launch the script directly. Since it has a shebang line, it will be parsed by Bash. Most of the other forms you use above actually run Bash twice - Once when launching WSL and another when it finds the shebang line in the script.
Try some basic troubleshooting for your script like:
Add set -x to the top (right under the shebang line) to turn on script debugging.
Add a ps -efH at the end to show the processes that are running when the script completes
If needed, resort to quick-and-dirty echo statements to show where things have progressed in the script.
I'm hopeful that the above will at least show you the problem, but if not, add the debugging info that you gain from this to your question, and we can troubleshoot further.

Old version of script is run unless invoked with "sh scriptname"

I'm making a small edit to a shell script I use to mask password inputs like so:
#!/bin/bash
printf "Enter login and press [ENTER]\n"
read user
printf "Enter password and press [ENTER]\n"
read -s -p pass
With the read -s -p pass being the updated part. For some reason I'm not seeing the changes when I run it normally by entering script.sh into the command line but I do see the changes when I run sh script.sh. I've tried opening new terminal windows, and have run it in both ITerm and the default Mac terminal. I'm far from a scripting master, does anyone know why I'm not seeing the changes without the prefix?
Use a full or relative path to the script to make sure you're running what you think you're running.
If you are running it as simply script.sh then the shell will PATH environment variable lookup to locate it. To see which script.sh bash would be using in that case, run type script.sh.
Relative Path
./script.sh
Full Path
/path/to/my/script.sh

sudo: command not found while using plink

Hi i have created a batch file (run.bat) that after execution connects me to UNIX server with help of plink. But issue starts from this point i have to execute a script after connection to my server the script contains a command sudo -l. After the execution i get the error as mentioned in subject can anyone help me on this issue ??
Batch File-:
"C:\Program Files\PuTTY" plink -ssh -pw Tos#12Ts w44dvftyw#caa1607UX009.wvd.abcd.net /opt/sieb/w44dvftyw/run.sh
Script file(run.sh) -:
#!/bin/bash
sudo -l
It says
sudo: command not found
But when i run my script normally on UNIX server it runs with no issues. What am i missing here to make it work this way please help.
Scripts such as ~/.profile or ~/.bash_profile responsible for setting up the current user's PATH are run only on login shells.
Running sh -c 'somescript' (as performed by ssh host 'somescript') is neither a login shell, nor an interactive shell; thus, it does not gain the benefit of such scripts.
This means that additions to the PATH (in your case, /usr/local/bin) may not be present with commands run in this way.
Among your options:
Pass the PATH you want as part of the command to remotely run. This might look like:
plink -ssh user#host "PATH=/bin:/usr/bin:/usr/local/bin /opt/sieb/w44dvftyw/run.sh"
Embed a working value in the script you're running:
#!/bin/bash
PATH=/bin:/usr/bin:/usr/local/bin
# ...put the rest of your script here.

From cmd, log into Bash and run command in one line

I am developing a TIBCO application and need to be able to run a scp command from an external command resource.
Anyway the issue boils down to being able to log in to bash.exe then run my scp command in the same line.
it works when I run (from cmd.exe)
c:\cygwin\bin\bash.exe --login
(I enter bash)
Then I can run my scp statement just fine
scp account#server:~mysourcedirectory/targetfilename* /cygdrive/c/targetfolder
I want to do these two things in the same line but it doesnt work, aka
c:\cygwin\bin\bash.exe --login -c scp account#server:~mysourcedirectory/targetfilename* /cygdrive/c/targetfolder
will fail. What am I doing wrong and how can i run this command in one go?
Thanks
You have to quote the command.
c:\cygwin\bin\bash.exe --login -c "scp account#server:~mysourcedirectory/targetfilename* /cygdrive/c/targetfolder"
Tested using cmd in wine in gnu/linux. Single quotes did not work, I don't know all the quoting rules for cmd. But the above did work.

bash command doesnt seem to work, but its echo does?

Well, I'm new to linux so this may be a very newbie kinda of thing, here it goes:
I have a script in which I'm trying to send some different jobs to remote computers (in fact Amazon's EC2 instances), these jobs are in fact the same function which I run with different parameters.
eventually in the script code I have this line:
nohup ssh -fqi key.pem ubuntu#${Instance_Id[idx]} $tmp
if I do:
echo nohup ssh -fqi key.pem ubuntu#${Instance_Id[idx]} $tmp
I get:
nohup ssh -fqi key.pem ubuntu#ec2-72-44-41-228.compute-1.amazonaws.com '(nohup ./Script.sh 11 1&)'
Now the weird thing. If I run the code with no echo in the script it doesnt work! it says in the nohup.out (in my laptop, no nohup.out is created in the remote instance) bash: (nohup ./Script.sh 10 1&): No such file or directory
The file does exist locally and remotely and is chmod +x.
If I simply run the very same script with an echo in front of the problematic line and copy its output and paste in the terminal, it works!.
Any clues welcome, thanks!
Try removing the single quotes from $tmp. It looks like bash is treating (nohup ./Script.sh 10 1&) as the command with no parameters, but technically nohup is the command with the parameters ./Script.sh 10 1.
The problem is the single quotes around the nohup command in your $tmp variable. These don't get used on the shell locally, so SSH passes them verbatim. This means remotely the ssh server tries to interpret (nohup ./Script.sh 10 1&) as a command (looks for a file named that) which there clearly isn't. Make sure you remove the single quotes in $tmp.

Resources