I want to execute a shell command/script using puppet only when a file exists in particular path.
For example if a text file test.txt exists in /root path then puppet will execute shell script, otherwise puppet didn't execute any commands
You should have done a little research before posting this question. But nevermind..
exec {"Comment to your resource":
command => 'your command',
provider => shell,
onlyif => '/usr/bin/test -e /path/to/file/test.txt',
}
onlyif will execute the command in Exec if and only if the command executed(in the onlyif) has return code 0.
Related
I am writing a a bash script (echoo.sh) with the intention of echoing the command before it is executed. I source this script (echoo.sh) inside .bashrc. But it does not execute for commands run in script file(tmp.sh) with the bash shebang. Below is the code I have so far
echoo.sh
#!/usr/bin/env bash
shopt -s extdebug; get_hacked () {
[ -n "$COMP_LINE" ] && return # not needed for completion
[ "$BASH_COMMAND" = "$PROMPT_COMMAND" ] && return # not needed for prompt
local this_command=$BASH_COMMAND;
echo $this_command;
};
trap 'get_hacked' DEBUG
When I open a shell and run any command - It works. But for stuff in a script file it doesn't work.
SOME FURTHER TRIES:
I tried sourcing the .bashrc file within the script file (tmp.sh) - didn't work.
I sourced echoo.sh inside tmp.sh and it worked.
SO, I am trying to understand
Why doesn't it work if I just source my script in .bashrc for stuff that runs in scripts?
Why doesn't further try #1 work when #2 does.
AND finally what can I do such that I don't have to source echoo.sh in all script files for this to work. Can source my script in one place and change some setting such that it works in all scenarios.
I source this script (echoo.sh) inside .bashrc. But it does not execute for commands run in script file(tmp.sh) with the bash shebang
Yes it won't because you are invoking the shell non-interactively!
The shell can be spawned either interactively or non-interactively. When bash is invoked as an interactive login shell it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable.
When an interactive shell that is not a login shell is started, bash reads and executes commands from ~/.bashrc, if that file exists.
When you run a shell script with an interpreter set, it opens a new sub-shell that is non-interactive and does not have the option -i set in the shell options.
Looking into ~/.bashrc closely you will find a line saying
# If not running interactively, don't do anything
[[ "$-" != *i* ]] && return
which means in the script you are calling, e.g. consider the case below which am spawning a non-interactive shell explicitly using the -c option and -x is just to enable debug mode
bash -cx 'source ~/.bashrc'
+ source /home/foobaruser/.bashrc
++ [[ hxBc != *i* ]]
++ return
which means the rest of the the ~/.bashrc was not executed because of this guard. But there is one such option to use here to read a start-up file for such non-interactive cases, as defined by BASH_ENV environment variable. The behavior is as if this line is executed
if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi
You can define a file and pass its value to the local environment variable
echo 'var=10' > non_interactive_startup_file
BASH_ENV=non_interactive_startup_file bash -x script.sh
Or altogether run your shell script as if an interactive non login shell is spawned. Run the script with an -i flag. Re-using the above example, with the -i flag passed now the ~/.bashrc file will be sourced.
bash -icx 'source ~/.bashrc'
You could also set this option when setting your interpreter she-bang in bash to #!/bin/bash -i
So to answer your questions from the above inferences,
Why doesn't it work if I just source my script in .bashrc for stuff that runs in scripts?
It won't because ~/.bashrc cannot be sourced from a shell that is launched non-interactively. By-pass it by passing -i to the script i.e. bash -i <script>
Why doesn't further try #1 work when #2 does.
Because you are depending on reading up the ~/.bashrc at all here. When you did source the echoo.sh inside tmp.sh, all its shell configurations are reflected in the shell launched by tmp.sh
Obviously I am doing something wrong here.
Cloud init script /etc/cloud/cloud.cfg
...
runcmd:
- [ sh, /opt/cloud-init-scripts/whatever.sh ]
The script /opt/cloud-init-scripts/whatever.sh
#!/bin/bash
...
. /home/ubuntu/third-party/script.sh --silent
Third party script /home/ubuntu/third-party/script.sh
#!/usr/bin/env bash
function some_function() {
...
Error I am getting in /var/log/cloud-init-output.log
/opt/cloud-init-scripts/whatever.sh: 3: /home/ubuntu/third-party/script.sh: Syntax error: "(" unexpected
I must be missing something obvious here. I tried using source, . and sh when calling the third party script, tried changing shebangs everywhere but no success.
If I run the same command from command line it works.
You have specified sh shell under runcmd, but have she-bang set to bash. The latter does not matter because if you run as sh /opt/cloud-init-scripts/whatever.sh it will be run with sh shell. I guess you are probably using a non POSIX shell feature which is incompatible with the sh shell.
Or alternatively if your intention is to run the script in bash shell, change the runCmd in cloud-init script to
runcmd:
- [ bash, /opt/cloud-init-scripts/whatever.sh ]
The following are two shell scripts stored in the same folder with execute permissions on both:
shell1.sh
#!/bin/bash
exec shell2.sh
shell2.sh
#!/bin/bash
pwd
When trying to execute shell1.sh I am getting the following error:
./shell1.sh: line 3: exec: shell2.sh: not found
Is there something I am doing incorrectly? This works in other machines though but just in one particular server its not working.
Any suggestions would be helpful.
The current dir is not part of your PATH.
Try
exec ./shell2.sh
I have an application named puppet installed on my Linux box. It is installed at location /usr/test/bin/puppet
This is how .bash_profile looks
export PATH=/usr/test/bin
if I run command puppet apply from console, it works fine but when I call puppet command from inside bash script, it says command not found
#!/bin/bash
puppet apply x.pp
Any ideas on what is wrong ?
.bash_profile is loaded only if bash is invoked as login shell (bash -l or from a real tty), at least in Debian based distributions bash in a virtual tty (for example when using xterm, gnome-terminal, etc...) is invoked as interactive shell.
Interactive shells loads the configuration from ~/.bashrc.
bash manpage:
~/.bash_profile
The personal initialization file, executed for login shells
~/.bashrc
The individual per-interactive-shell startup file
Shellscripts don't load any of these.
You can check which files are opened by any program with strace:
strace ./s.sh 2>&1 | grep -e stat -e open
Possible solutions:
You can export the variable at the beginning of every script:
#!/bin/bash
export PATH=$PATH:...
Or you can have another file with the desired variables and source it from any script that need those:
/etc/special_vars.sh:
export PATH=$PATH:...
script:
#!/bin/bash
. /etc/special_vars.sh
puppet ...
Configure the PATH in in ~/.bashrc, ~/.bash_profile and ~/.profile for the user running the script (sub-processes will inherit the environment variables) to have some warranty that the user can run the script from different environments and shells (some bourne compatible shells others than bash do load ~/.profile)
Maybe the export of PATH is wrong?
export PATH=$PATH:/usr/test/bin/puppet
You could try using an alias, like so
in your .bash_profile:
alias puppet='bash puppet.fileextension'
you can also do
alias puppet='bash path/to/puppet.fileextension'
which will let you run the script from anywhere in Terminal.
EDIT:
OP has stated in the comments that there will be two different systems running, and he asked how to check the file path to the bash file.
If you do
#!/bin/bash
runPuppet(){
if [ -e path/to/system1/puppet.fileextension]
then
bash path/to/system1/puppet.fileextension $1 $2
elif [ -e path/to/system2/puppet.fileextension]
then
bash path/to/system2/puppet.fileextension $1 $2
fi
}
runPuppet apply x.pp
and change the runPuppet input to whatever you'd like.
To clarify/explain:
-e is to check if the file exists
$1 & $2 are the first two input parameters, respectively.
I am having a bash script that is executing another bash script:
ex:
script name "rotator" is calling script name "s3-get" like below
!# /bin/bash
...
./s3-get {and params here}
All commands as "cat", "basename" etc. run correctly here
Within the "s3-get" script there is code as:
!# /bin/bash
cat > /dev/null << EndOfLicense
...
readonly weAreKnownAs="$(basename $0)"
...
main "$#"
So, if I simply execute the s3-get script directly from shell, it runs perfectly. When I try to execute it from "rotator" script, I get the error "cat: command not found". I can fix this by changing "cat" with "/bin/cat" just that I don't think this is correct since, as I stated above, the script runs correctly when executed as standalone. If I fix the "cat" command as above, the next error that raises is "basename: command not found", then "main: command not found"
I am pretty new to shell programming, so any help is appreciated.
Thank you
Try $ echo 'export PATH=$PATH:/root/scripts/RotateVideos' >> ~/.bashrc && source ~/.bashrc in the command line and then just call it using s3-get in your script. Alternatively use cd /root/scripts/RotateVideos && bash s3-get.