I've hit a snag with a shell script intended to run every 30 minutes in cron on a Redhat 6 server. The shell script is basically just a command to run a python script.
The native version python on the server is 2.6.6 but the python version required by this particular script is python 2.7+. I am able to easily run this on the command line by using the "scl" command (this example includes the python -V command to show the version change):
$ python -V
Python 2.6.6
$ scl enable python27 bash
$ python -V
Python 2.7.3
At this point I can run the python 2.7.3 scripts on the command line no problem.
Here's the snag.
When you issue the scl enable python27 bash command it starts a new bash shell session which (again) is fine for interactive commandline work. But when doing this inside a shell script, as soon as it runs the bash command, the script exits because of the new session.
Here's the shell script that is failing:
#!/bin/bash
cd /var/www/python/scripts/
scl enable python27 bash
python runAllUpserts.py >/dev/null 2>&1
It simply stops as soon as it hits line 4 because "bash" pops it out of the script and into a fresh bash shell. So it never sees the actual python command I need it to run.
Plus, if run every 30 minutes, this would add a new bash each time which is yet another problem.
I am reluctant to update the native python version on the server to 2.7.3 right now due to several reasons. The Redhat yum repos don't yet have python 2.7.3 and a manual install would be outside of the yum update system. From what I understand, yum itself runs on python 2.6.x.
Here's where I found the method for using scl
http://developerblog.redhat.com/2013/02/14/setting-up-django-and-python-2-7-on-red-hat-enterprise-6-the-easy-way/
Doing everything in one heredoc in the SCL environment is the best option, IMO:
scl enable python27 - << \EOF
cd /var/www/python/scripts/
python runAllUpserts.py >/dev/null 2>&1
EOF
Another way is to run just the second command (which is the only one that uses Python) in scl environment directly:
cd /var/www/python/scripts/
scl enable python27 "python runAllUpserts.py >/dev/null 2>&1"
scl enable python27 bash activates a python virtual environment.
You can do this from within a bash script by simply sourcing the enable script of the virtual environment, of the SCL package, which is located at /opt/rh/python27/enable
Example:
#!/bin/bash
cd /var/www/python/scripts/
source /opt/rh/python27/enable
python runAllUpserts.py >/dev/null 2>&1
Isn't the easiest to just your python script directly? test_python.py:
#!/usr/bin/env python
import sys
f = open('/tmp/pytest.log','w+')
f.write(sys.version)
f.write('\n')
f.close()
then in your crontab:
2 * * * * scl python27 enable $HOME/test_python.py
Make sure you make test_python.py executable.
Another alternative is to call a shell script that calls the python. test_python.sh:
#/bin/bash
python test_python.py
in your crontab:
2 * * * * scl python27 enable $HOME/test_python.sh
One liner
scl enable python27 'python runAllUpserts.py >/dev/null 2>&1'
I use it also with the devtoolsets on the CentOS 6.x
me#my_host:~/tmp# scl enable devtoolset-1.1 'gcc --version'
gcc (GCC) 4.7.2 20121015 (Red Hat 4.7.2-5)
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
scl is the dumbest "let us try and lock you in` nonsense I've seen in a while.
Here's how I made it so I could pass arguments to a series of scripts that all linked to a single skeleton file:
$ cat /usr/bin/skeleton
#!/bin/sh
tmp="$( mktemp )"
me="$( basename $0 )"
echo 'scl enable python27 - << \EOF' >> "${tmp}"
echo "python '/opt/rh/python27/root/usr/bin/${me}' $#" >> "${tmp}"
echo "EOF" >> "${tmp}"
sh "${tmp}"
rm "${tmp}"
So if there's a script you want to run that lives in, say, /opt/rh/python27/root/usr/bin/pepper you can do this:
# cd /usr/bin
# ln -s skeleton pepper
# pepper foo bar
and it should work as expected.
I've only seen this scl stuff once before and don't have ready access to a system with it installed. But I think it's just setting up PATH and some other environment variables in some way that vaguely similar to how they're done under virtualenv.
Perhaps changing the script to have the bash subprocess call python would work:
#!/bin/bash
cd /var/www/python/scripts/
(scl enable python27 bash -c "python runAllUpserts.py") >/dev/null 2>&1
The instance of python found on the subprocess bash's shell should be your 2.7.x copy ... and all the other environmental settings done by scl should be inherited thereby.
Related
I installed bash-5.1 via Homebrew on my Macbook (M1-Monterey).
sachetz$ /opt/homebrew/bin/bash --version
GNU bash, version 5.1.16(1)-release (aarch64-apple-darwin21.1.0)
Added the path to /etc/shells file:
/bin/bash
/bin/csh
/bin/dash
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh
/opt/homebrew/bin/bash
And ran the following command to set bash-5.1 as the default:
sachetz$ chsh -s /opt/homebrew/bin/bash
However, when I restart terminal and run the bash --version command, I still see bash-3.2:
sachetz$ bash --version
GNU bash, version 3.2.57(1)-release (arm64-apple-darwin21)
Copyright (C) 2007 Free Software Foundation, Inc.
But if I run echo $BASH_VERSION, I see bash-5.1
sachetz$ echo $BASH_VERSION
5.1.16(1)-release
Running which bash gives:
sachetz$ which bash
/bin/bash
Running echo $SHELL gives:
sachetz$ echo $SHELL
/opt/homebrew/bin/bash
When I run an echo $PATH with zsh as the default, I see /opt/homebrew/bin:
% echo $PATH
/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin:/Library/Frameworks/Mono.framework/Versions/Current/Commands
However, if I run the same after the chsh to Homebrew bash, I see:
sachetz$ echo $PATH
/Applications/XAMPP/xamppfiles/bin:/Applications/XAMPP/xamppfiles/bin/php:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin:/Library/Frameworks/Mono.framework/Versions/Current/Commands
I'm guessing the issue here is that /opt/homebrew/bin:/opt/homebrew/sbin is not present in the $PATH after I switch the default to Homebrew bash and restart the terminal. So the question is, why is the path variable different between the two, and how do I fix the issue?
Just needed to add /opt/homebrew/bin:/opt/homebrew/sbin: to the PATH variable in ~/.bash_profile like:
export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:$PATH"
I suppose I missed this out as an installation step or something.
You might want to check the profiles, I believe bash checks both ~/.bashrc and ~/.bash_profile. Typically the $PATH are setup there.
For zsh, it looks at ~/.zshrc.
Also, you can check to see Terminal > Preference > Shells open with... option in the Terminal app.
which bash looks for bash under your path and bash --version is running a new bash from your path. If your path points to /bin/bash first, they'll give that bash's path/version. This isn't the correct way to verify the current shell's version.
The $BASH_VERSION & $SHELL point to the current shell and looks like it is already running the correct version.
You could also try new built-in variables, like
echo $EPOCHSECONDS
I am trying to create a shell script that runs several scripts under CentOS 7. Each script starts with #!/bin/bash. Each script is tested and can be run as a standalone shell script with no problem.
Content of scripts_all.sh
#!/bin/bash
set -x
sudo yum install g++ make binutils cmake openssl-devel boost-devel zlib-devel
sh script_1.sh # executes all the contents of script_1.sh
sh script_2.sh # does not executed any of the command in script_2.sh.
sh script_3.sh
sh script_4.sh
script_1.sh
#!/bin/bash
sudo yum install centos-release-scl
sudo yum install devtoolset-9-gcc*
scl enable devtoolset-9 bash
which gcc
gcc --version
script_2.sh
#!/bin/bash
sudo yum install centos-release-scl-rh
sudo yum-config-manager --enable centos-release-scl-rh
sudo yum install devtoolset-9
scl enable devtoolset-9 bash
It appears that ./scripts_all.sh will successfully execute set -x, sudo yum, sh script_1.sh but stops at sh script_2.sh. It is worth noting that I can run sh script_2.sh with no issue independent of scripts_all.sh. I don't know why the rest of the scripts won't be run.
./scripts_all.sh prints the lines of sh script_1.sh and their executions but it never prints the lines of sh script_2.sh.
Could someone kindly help?
Copying comments into the semblance of an answer.
Change the sh script_1.sh etc lines to bash -x script_1.sh (or sh -x script_1.sh since the scripts don't seem to use any Bash-specific syntax) and monitor what's going on. Do you see the version information from gcc --version in script_1.sh?
gcc --version is only printed when I comment out scl enable devtoolset-9 bash. I ran scl enable devtoolset-9 bash and it does not output anything to the screen.
That suggests the scl command is not completing. Maybe it is waiting for input from the terminal. Do you see the output from which gcc when you include the scl command? If not, then it is close to certain that scl is trying to read from the terminal. I dunno what it's reading — it isn't a command I'm familiar with.
It is not waiting for any input. After execution, it brings the prompt again when I run it by itself.
If you're not seeing the which gcc and gcc --version output, then it is probable that the scl command is not completing, IMO. What does the bash at the end of the command options do? Does it run a bash process? If so, where is its input coming from? Running with the -x option (sh -x script_1.sh) would show you what is being executed, and whether scl is completing.
scl enable foo bar bash actually runs a bash instance with foo and bar Software Collections enabled. See https://linux.die.net/man/1/scl
OK; and what is that bash instance doing? Is it not waiting for input before it executes anything? It's a little surprising that there isn't a prompt, but not completely astonishing. Have you tried typing exit when scl hangs?
I just tried scl enable devtoolset-9 bash & echo "Enabling devtoolset-9" and it works and ultimately prints out the gcc --version.
Well, that & runs the scl command in background, leaving the echo to run, and then which gcc and gcc --version. Replace the & with a semicolon. Or replace the & with -c 'echo Hi' and a semicolon and see what happens.
Wonderful! Adding -c echo "Hi" made it work!
So that bash command specified at the end of scl enable devtoolset-9 bash was waiting for input from you, which is why it didn't terminate (and you don't see which gcc running) and so on. You've got the same issue at the end of script_2.sh — what about the other scripts? But you now know what's going on and can decide what to do about it. Using -c exit would simply terminate the shell (instead of echoing Hi), for example.
I'd need to study the scl command more, but do you actually need to use it in these scripts?
I have been trying to resolve problems to be able to run openmpi on multiple nodes.
Initially I had a problem with $PATH and $LD_LIBRARY_PATH variables not being updated from .bashrc file by openmpi session, so I manually added --prefix /path/to/openmpi to resolve this issue.
Turns out that even the anaconda path variables are not being loaded as well. So ultimately I need ~/.bashrc file to be sourced from my home directory. How can I do that? Can anyone help me out please?
UPDATE 01:
I wrote a simple shell script to check the version of python
python --version
and tried to run it with openmpi on local as well as remote machine as follows:
mpirun --prefix /home/usama/.openmpi --hostfile hosts -np 4 bash script
And it returns
Python 2.7.12
Python 3.6.8 :: Anaconda, Inc.
Python 3.6.8 :: Anaconda, Inc.
Python 2.7.12
Confirming my suspicion that whatever openmpi is doing to run remote processes doesn't invoke / set proper environment variables from the ~/.bashrc file. Any help from someone who has worked with multi-node openmpi?
UPDATE 02:
A simple ssh environment grep tell me that my environment variables are not updated which might be the cause of the problem. (I have even tried to set it up in ~/.ssh/environment file)
$ ssh remote-node env | grep -i path
It seems to be loading only the /etc/environment file with only basic paths setup. How to I rectify this?
maybe you should run like this.I guess.
two ways help you!
first:
mpirun --prefix /home/usama/.openmpi --hostfile hosts -np 4 . ~/.bashrc && bash script
second:
## 1. add this line to the script
. ~/.bashrc
## 2. run command as you do
mpirun --prefix /home/usama/.openmpi --hostfile hosts -np 4 bash script
I tried to execute a shell script on AIX and it failed because some declaration/instructions (like readarray, array declaration, date command with specific args etc) from shell is not recognized in ksh
I would like to execute this linux script on AIX without rewrite the entire script in ksh.
I tried to run the script using different shebang like #!/usr/bin/env bash or #!/bin/sh but AIX seems still running it through ksh.
Would someone have a solution to run linux shell on AIX ?
« AIX Toolbox for Linux Applications » seems provide to execute linux shell on AIX.
Could someone confirm me this information ?
How can I check if AIX Toolbox is already install on the AIX server ? (i don’t have the administration right on this server)
How to execute AIX Toolbox to run shell script ?
Thanks in advance for your help
As you can see from the link you can install AIX Toolbox for Linux Applications and you will have bash. Also you can download only this package and install it.
After install you can exec bash as any other program in your OS.
But in generally you can reach a lot of challenges when try to run linux script on AIX or HP-UX.
You can use bash! Need to install yum from here. Once yum is installed it will auto-install bash package.
Put in a temporary empty folder, untar it and install all RPMs: rpm -Uvh *.rpm.
Edit /etc/security/login.cfg anb and "/usr/bin/bash" in the end:
shells = /bin/sh,/bin/bsh,/bin/csh,/bin/ksh,/bin/tsh,/bin/ksh93,/usr/bin
/sh,/usr/bin/bsh,/usr/bin/csh,/usr/bin/ksh,/usr/bin/tsh,/usr/bin/ksh93,/usr/bin/
rksh,/usr/bin/rksh93,/usr/sbin/uucp/uucico,/usr/sbin/sliplogin,/usr/sbin/snappd,
/usr/bin/bash
Add path /usr/bin/bash to /etc/shells:
# echo “/usr/bin/bash” >> /etc/shells
Change shell to se bash:
# chuser shell=/usr/bin/bash root
Create a new .bash_profile inside root's home with:
# .bash_profile
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
PS1="[\u#\h \w]\$ "
export PS1
Login with root and you see something like this:
[root#aixserver ~]#
I'm trying to start unicorn_rails in a ruby script, and after executing many commands in the script, when the script gets to the following line
%x[bash -ic "bash <(. ~/.bashrc); cd /home/www-data/rails_app; bundle exec unicorn_rails -p 8000 -E production -c /home/www-data/rails_app/config/unicorn.rb -D"]
the script stops, generating the following output
[1]+ Stopped ./setup_rails.rb
and returns to the Linux prompt. If I type "fg", the script finishes running, the line where the script had stopped gets executed and unicorn gets started as a daemon.
If I run the line in a separate script, the script completes without stopping.
UPDATE_1 -
I source .bashrc because earlier in the script I install rvm and to get it to run with the correct environment I have the following:
%x[echo "[[ -s \"$HOME/.rvm/scripts/rvm\" ]] && source \"$HOME/.rvm/scripts/rvm\"" >> .bashrc]
%x[bash -ic "bash <(. ~/.bashrc); rvm install ruby-1.9.2-p290; rvm 1.9.2-p290 --default;"]
So if I want to run correct version of rvm, ruby and bundle I need to source .bashrc
end UPDATE_1
Does anyone have any idea what could cause a ruby script to halt as if control-Z was pressed?
Not sure why it's stopping, but my general rule of thumb is to never source my .bashrc in a script -- that might be the source of your problem right there, but I can't be sure without seeing what's in it. You should be able to change your script to something like:
$ vi setup_rails.sh
#!/usr/bin/bash
# EDIT from comments below
# expanding from a one liner to a better script...
$RVM_PATH=$HOME/.rvm/scripts
# install 1.9.2-p290 unless it's installed
$RVM_PATH/rvm info 1.9.2-p290 2&>1 >/dev/null || $RVM_SH install 1.9.2-p290
# run startup command inside rvm shell
$RVM_PATH/rvm-shell 1.9.2-p290 -c "cd /home/www-data/rails_app && bundle exec unicorn_rails -p 8000 -E production -c /home/www-data/rails_app/config/unicorn.rb -D"
This should give you the same result.