Chef bash resource, command attribute doesn't work - bash

I have a simple recipe that looks like this:
bash "create folder" do
command "mkdir -p /home/user/folder"
not_if {::File.directory?("/home/user/folder")}
end
It doesn't work. It says that it's executing, but it doesn't create the folder. If I change bash to execute then it works. If I change command to code then it works. But the bash and execute docs have literally the same specs on command.
Am I doing something wrong or are the docs wrong?

To quote the attributes documentation of the Bash resource:
code: A quoted (” ”) string of code to be executed.
command: The name of the command to be executed. Default value: the name of the resource block (see Syntax section above).
This, the command attribute is just the name of the command, not the full code to run. With the bash resource (and all the other script resources), you should use the code attribute to send the code to be executed.
The correct resource definition is thus:
bash "create folder" do
code "mkdir -p /home/user/folder"
not_if {::File.directory?("/home/user/folder")}
end
In fact, the contents of the command attribute is not used there anywhere, it's just there because the script resource inherits from the execute resource and thus inherits all its possible attributes.
As a final remark, to create a directory, you should use the actual idiomatic directory resource built-in to Chef instead of a bash script like this:
directory "/home/user/folder" do
recursive true
end

The default behavior of bash is Use to run a script.
The default behavior of execute is Use to run a command.
You are running a command, not a script, so it makes sense you should be using a code block or using execute instead. The difference between the two is... not well defined in the docs. I have found at least 3 or 4 examples in the docs that were outright wrong and submitted corrections, some of which still haven't been made.

Related

How can I store and execute the command "export PATH=$PREFIX/bin" from a script?

I would like to write a script that has several commands of the kind
> export PATH=$PREFIX/bin
Where
> $PREFIX = /home/usr
or something else. Instead of typing it into the the Shell (/bin/bash) I would run the script to execute the commands.
Tried it with sh and then with a .py script having the line,
> commands.getstatusoutput('export PATH=$PREFIX/bin')
but these result into the error "bad variable name".
Would be thankful for some ideas!
If you need to adjust PATH (or any other environment variable) via a script after your .profile and equivalents have been run, you need to 'dot' or 'source' the file containing the script:
. file_setting_path
source file_setting_path
The . notation applies to all Bourne shell derivatives, and is standardized by POSIX. The source notation is used in C shell and has infected Bash completely unnecessarily.
Note that the file (file_setting_path) can be specified as a pathname, or if it lives in a directory listed on $PATH, it will be found. It only needs to be readable; it does not have to be executable.
The way the dot command works is that it reads the named file as part of the current shell environment, rather than executing it in a sub-shell like a normal script would be executed. Normally, the sub-shell sets its environment happily, but that doesn't affect the calling script.
The bad variable name is probably just a complaint that $PREFIX is undefined.
Usually a setting of PATH would look something like
export PATH=$PATH:/new/path/to/programs
so that you retain the old PATH but add something onto the end.
You are best off putting such things in your .bashrc so that they get run every time you log in.

How to setup a "module" command in unix to add software package to $PATH?

I use a lot of computing clusters and these often use a module system for making software packages available. Basically, you use the module command like module load sample_software and the sample_software path is added to $PATH. On a cluster, this command can be invoked during interactive usage and job submission usage.
I have a linux box with PBS/Torque queueing system installed so that I can sandbox software for later use on clusters. I need a very similar module system on this box. I started by making a file called modules.sh in my `/etc/profile.d/ directory that looks like this:
module()
{
if [ $2 == "softwareX" ]; then
PATH=$PATH:/home/me/dir/softwareX
export PATH
fi
}
I then put the following line in my .bash_profile script:
source /etc/profile.d/modules.sh
Now, this works great for the following usages: 1) If I submit a job and my job script uses module load softwareX, no problem, the job runs perfectly. 2) If I am working interactively on the command line and I type module load softwareX, then the path to softwareX is loaded into my $PATH and everything works great.
However, this doesn't work for the following situation: If I make a simple bash script that contains the line module load softwareX, when the bash script executes I get an error. For example, here is my bash script:
#!/usr/bin/env bash
echo $PATH
module load softwareX
echo $PATH
When I execute this I receive the error script.sh: line 3L module: command not found
...and the $PATH never changes. Does anyone know how I can solve this problem to work in all three situations? Thanks for any help!
A bash script won't invoke your startup files. You have to do that explicitly.
See http://www.gnu.org/software/bash/manual/bashref.html#Bash-Startup-Files
Invoked non-interactively
When Bash is started non-interactively, to run a shell script, for example, it looks for the variable BASH_ENV in the environment, expands its value if it appears there, and uses the expanded value as the name of a file to read and execute. Bash behaves as if the following command were executed:
if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi
but the value of the PATH variable is not used to search for the file name.
As noted above, if a non-interactive shell is invoked with the --login option, Bash attempts to read and execute commands from the login shell startup files.
When you create a sub-shell, you create a new environment. When you exit back to your existing shell, you lose that environment.
I suspect this is what is going on with your module function call. If you added echo $PATH to the bottom of your module function, do you see the PATH get changed while inside the function, but changes again when you leave the function? If so, the problem is a sub-shell issue:
What you SHOULD do is have your module function print out the new path, and then do this:
PATH=$(module load softwareX)

How to put a variable in the path of a command being executed in a Bash script

presently I'm working on a Bash script, and I am having trouble with writing a particular portion of the script. Basically I read in an appName using the read command in the bash script, and then I want to run a command with the appName variable in the path, but when I run the script it just prints $appName not the variable itself.
The part of the script I am describing looks like the following,
echo "Input the name of the app"
read appName
echo "The AppName is: "$appName
dotApp=.app
ldid -S DerivedData/$appName/Build/Products/*/$appName$dotApp
The script you posted should work as is. Make sure the code you pasted is the actual code you run.
Putting single quotes around the string is the typical error that causes the problem you describe, but you don't have that in your posted example.

Using custom script inside .profile file in ksh

I am trying to use a script that takes in some parameters inside my .profile file. The script is basically to execute a particular operation(from a set) on a list of jobs. So I execute the script like this.
sh bulkCommandProcessor.sh commandName job1 job2 job3...
Since the number of commands that can go in as the first argument is only 7, I would like to have aliases for each of it in my .profile file. I tried the following.
alias bjr='sh /home/vijay/scripts/bulkCommandProcessor.sh jr'
However, this doesnt seem to work. The error handling part of my code gets displayed when I source the .profile file which says something like this.
usage: /home/vijay/scripts/bulkCommandProcessor.sh cmd Job_name1 Job_name2 Job_name3 ..
Is there a way to achieve what I intend? That is use a script that accepts variable length of arguments within the .profile file.
First I think you need to make sure that your script bulkCommandProcesor.sh has the right permissions, that it is in the right path and that your are correctly parsing arguments for your script. I think that the following template might work:
#!/usr/bin/ksh
# .profile example
alias bjr='sh /home/vijay/scripts/bulkCommandProcessor.sh jr'
#variable length arguments in jobs
#where you previously get job1,job2 for example
jobs="$job1 $job2"
#And finally calling your script
bjr $jobs

Adding a shell script to be executed with the 'mrt/meteor create' command in terminal

How can I run a shell script that is executed when I enter the 'mrt create' command in the terminal?
Great question Johann!
Alright, so to turn a shell script into something as convenient as a terminal command, all you need to do is create an alias for that script in your terminal's rc file. Further instructions as to how you can do that can be found here.
So all you need to do is list out the commands you want automated in the shell script, including the meteor/mrt commands, and pass the directory/project name with the special variable "$1" passes the first argument after your command into your script.
Here's the script I am currently using, which implements the folder structure from Discover Meteor and adds coffeescript and stylus-mixins There are probably some redundancies in commands. Let me know if you see anything that can be cleaned!

Resources