Dynamically getting Properties in shell script - bash

I want to keep a mailing functionality in my shell script, where I can dynamically decide who are the mail recipients; I have defined a prop file which looks like this:
test.properties
servers=primserver1#secserver1
mailrecipients=XXX#abc.com
primserver1-mailrecipients=abc#xxx.com
Now, I want to implement the script in such a way, that if I have property servername-mailrecipients in the property file, then the mail should be sent to these recipients, otherwise mail should be sent to the ids in mailrecipients property.
this is shell script I am writing:
test.sh
#!/bin/bash
#Script for establishing connection between DMZ server and EMS server
scriptsroot=/app/test
cd "$scriptsroot/properties/test" || exit
if [ -f "test.properties" ]; then
echo "Loading Property File: test.properties"
# shellcheck source=/dev/null
. ./test.properties
else
echo "Property File: test.properties does not exist"
exit;
fi
destservers=(${servers//#/ })
echo "${destservers[0]}; ${destservers[1]}"
echo "$mailrecipients"
echo "${${destservers[0]}-mailrecipients}"
However, I am getting following exception:
Output
Loading Property File: test.properties
./test.properties: line 3: primems1-mailrecipients=abc#xxx.com: command not found
primems1; secems1
XXX#abc.com
test.sh: line 23: ${${destservers[0]}-mailrecipients}: bad substitution
Please provide some suggestions

Related

My script is failing on an if/else statement

I was using this bitbucket backup code. On running bitbucket.diy-backup.sh, it exits from shell at an if statement in common.sh.
Attached relevant parts of code from both files -
bitbucket.diy-backup.sh -
set -e
SCRIPT_DIR=$(dirname "$0")
source "${SCRIPT_DIR}/utils.sh"
source "${SCRIPT_DIR}/common.sh"
common.sh -
BACKUP_VARS_FILE=${BACKUP_VARS_FILE:-"${SCRIPT_DIR}"/bitbucket.diy-backup.vars.sh}
...
# Just exits here
if [ -f "${BACKUP_VARS_FILE}" ]; then
source "${BACKUP_VARS_FILE}"
debug "Using vars file: '${BACKUP_VARS_FILE}'"
else
error "'${BACKUP_VARS_FILE}' not found"
bail "You should create it using '${SCRIPT_DIR}/bitbucket.diy-backup.vars.sh.example' as a template"
fi
Here is the file structure - all three files are in the same directory. Ideally, it should go through the first if statement, or maybe it goes to else. But running ./bitbucket.diy-backup.sh just exits at this statement.

bats - how can i echo the file name in a bats script for reporting

I have some bats scripts that I run to test some functionality
how can I echo the bats file name in the script?
my bats script looks like:
#!/usr/bin/env bats
load test_helper
echo $BATS_TEST_FILENAME
#test "run cloned mission" {
blah blah blah
}
in order for my report to appear as:
✓ run cloned mission
✓ run cloned mission
✓ addition using bc
---- TEST NAME IS xxx
✓ run cloned mission
✓ run cloned mission
✓ addition using bc
---- TEST NAME IS yyy
✓ run cloned mission
✓ run cloned mission
✓ addition using bc
but got the error
2: syntax error:
operand expected (error token is ".bats
2")
what is the correct way to do it?
I don't want to change the sets names for it only to echo the filename between different tests.
Thanks.
TL;DR
Just output the file name from the setup function using a combination of prefixing the message with # and redirecting it to fd3 (documented in the project README).
#!/usr/bin/env bats
setup() {
if [ "${BATS_TEST_NUMBER}" = 1 ];then
echo "# --- TEST NAME IS $(basename ${BATS_TEST_FILENAME})" >&3
fi
}
#test "run cloned mission" {
blah blah blah
}
All your options
Just use BASH
The simplest solution is to just iterate all test files and output the filename yourself:
for file in $(find ./ -name '*.bats');do
echo "--- TEST NAME IS ${file}"
bats "${file}"
done
The downside of this solution is that you lose the summary at the end. Instead a summary will be given after each single file.
Use the setup function
The simplest solution within BATS is to output the file name from a setup function. I think this is the solution you are after.
The code looks like this:
setup() {
if [ "${BATS_TEST_NUMBER}" = 1 ];then
echo "# --- TEST NAME IS $(basename ${BATS_TEST_FILENAME})" >&3
fi
}
A few things to note:
The output MUST begin with a hash #
The MUST be a space after the hash
The output MUST be redirected to file descriptor 3 (i.e. >&3)
A check is added to only output the file name once (for the first test)
The downside here is that the output might confuse people as it shows up in red.
Use a skipped #test
The next solution would be to just add the following as the first test in each file:
#test "--- TEST NAME IS $(basename ${BATS_TEST_FILENAME})" {
skip ''
}
The downside here is that there will be an addition to the amount of skipped tests...
Use an external helper function
The only other solution I can think of would be to create a test helper that lives in global scope and keeps tracks of its state.
Such code would look something like this:
output-test-name-helper.bash
#!/usr/bin/env bash
create_tmp_file() {
local -r fileName="$(basename ${BATS_TEST_FILENAME})"
if [[ ! -f "${BATS_TMPDIR}/${fileName}" ]];then
touch "${BATS_TMPDIR}/${fileName}"
echo "---- TEST NAME IS ${fileName}" >&2
fi
}
remove_tmp_file() {
rm "${BATS_TMPDIR}/$(basename ${BATS_TEST_FILENAME})"
}
trap remove_tmp_file EXIT
create_tmp_file
Which could then be loaded in each test:
#!/usr/bin/env bats
load output-test-name-helper
#test "run cloned mission" {
return 0
}
The major downside here is that there are no guarantees where the output is most likely to end up.
Adding output from outside the #test, setup and teardown functions can lead to unexpected results.
Such code will also be called (at least) once for every test, slowing down execution.
Open a pull-request
As a last resort, you could patch the code of BATS yourself, open a pull-request on the BATS repository and hope this functionality will be supported natively by BATS.
Conclusion
Life is a bunch of tradeoffs. Pick a solution that most closely fits your needs.
I've figured out a way to do this, but it requires you changing how you handle your individual setup in each file.
Create a helper file that defines a setup function that does as Potherca described above:
global.bash:
test_setup() { return 0; }
setup() {
(($BATS_TEST_NUMBER==1)) \
&& echo "# --- $(basename "$BATS_TEST_FILENAME")" >&3
test_setup
}
Then in your test, instead of calling setup you would just load 'global'.
If you need to create a setup for a specific file, then instead of creating a setup function, you'd create a test_setup function.
Putting the echo in setup outputs the file name after the test name.
What I wound up doing is adding the file name to the test name itself:
test "${BATS_TEST_FILENAME##*/}: should …" {
…
}
Also, if going the setup route, the condition can be avoided with:
function setup() {
echo "# --- $(basename "$BATS_TEST_FILENAME")" >&3
function setup() {
…
}
setup
}

Setting Puppet variables with a BASH command

I've been trying to set a variable in a Puppet manifest that can be used across the puppet run. I have the following variables:
$package = 'hello'
$package_ensure = 'present'
$package_version = '4.4.1'
$package_maj_version = '4'
I'm trying to add another variable:
$ensure
using a BASH If statement using the above variables (since this is a source install I can't use an rpm command to see if the hello program is installed):
if [ -d "/opt/${package}${package_maj_version}" ]; then echo present; else echo absent; fi
but, I haven't been able to find a way to do so. I keep getting errors such as:
Error: Could not parse for environment production: Could not match ${package}${package_maj_version}"
Any help on this would be greatly appreciated.

Create a command line script

I'm using a web tool that has inbound webhooks. They provide me with a URL, to which I can POST a string and it logs it into the system.
I would like to create a script that me and my team can use from the terminal to do something like this:
~: appName
~: What is the webHook URL?
Here I can copy and paste the URL gives me, and stores it.
Then from now I can do this:
~: appName This is a message that I want to send...
And this sends as a POST to the webhook the string. This would ideally something I can share with non-techies and that's easy to set up. And I have no idea how to even start this.
I am assuming you want this to be strictly shell.
In the end you want to use something like curl (bash)
curl --data "msg=$2" $url
The $url variable could come from a flat file(app.txt) that is just key value with key=appName
You first script would need to append to the file(app.txt)
echo $1 $2 >> app.txt
This is how you can get started:
#!/bin/bash
msg=$1
url=""
[ ! -f webhookurl ] || url=`cat webhookurl` #webhookurl is a file where you put the url
if [ "$url" == "" ]; then
read -p "What is the webHook URL? " url
echo $url > webhookurl
fi
# Now start posting message
curl --data "msg=$msg" $url
save it with appname. Then run appname like this:
./appname "message to send"
It will ask for url for the first time and save it in webhookurl file in the same folder as the script for future use.

Scripting Xcode documentation with DOxygen problems

I am trying to use the following script by duckrowing (http://www.duckrowing.com/2010/03/18/documenting-objective-c-with-doxygen-part-ii/), to document an existing xcode project.
#
# Build the doxygen documentation for the project and load the docset into Xcode
#
# Created by Fred McCann on 03/16/2010.
# http://www.duckrowing.com
#
# Based on the build script provided by Apple:
# http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
#
# Set the variable $COMPANY_RDOMAIN_PREFIX equal to the reverse domain name of your comany
# Example: com.duckrowing
#
DOXYGEN_PATH=/Applications/Doxygen.app/Contents/Resources/doxygen
DOCSET_PATH=$SOURCE_ROOT/build/$PRODUCT_NAME.docset
if ! [ -f $SOURCE_ROOT/Doxyfile]
then
echo doxygen config file does not exist
$DOXYGEN_PATH -g $SOURCE_ROOT/Doxyfile
fi
# Append the proper input/output directories and docset info to the config file.
# This works even though values are assigned higher up in the file. Easier than sed.
cp $SOURCE_ROOT/Doxyfile $TEMP_DIR/Doxyfile
echo "INPUT = $SOURCE_ROOT" >> $TEMP_DIR/Doxyfile
echo "OUTPUT_DIRECTORY = $DOCSET_PATH" >> $TEMP_DIR/Doxyfile
echo "RECURSIVE = YES" >> $TEMP_DIR/Doxyfile
echo "EXTRACT_ALL = YES" >> $TEMP_DIR/Doxyfile
echo "JAVADOC_AUTOBRIEF = YES" >> $TEMP_DIR/Doxyfile
echo "GENERATE_LATEX = NO" >> $TEMP_DIR/Doxyfile
echo "GENERATE_DOCSET = YES" >> $TEMP_DIR/Doxyfile
echo "DOCSET_FEEDNAME = $PRODUCT_NAME Documentation" >> $TEMP_DIR/Doxyfile
echo "DOCSET_BUNDLE_ID = $COMPANY_RDOMAIN_PREFIX.$PRODUCT_NAME" >> $TEMP_DIR/Doxyfile
# Run doxygen on the updated config file.
# Note: doxygen creates a Makefile that does most of the heavy lifting.
$DOXYGEN_PATH $TEMP_DIR/Doxyfile
# make will invoke docsetutil. Take a look at the Makefile to see how this is done.
make -C $DOCSET_PATH/html install
# Construct a temporary applescript file to tell Xcode to load a docset.
rm -f $TEMP_DIR/loadDocSet.scpt
echo "tell application \"Xcode\"" >> $TEMP_DIR/loadDocSet.scpt
echo "load documentation set with path \"/Users/$USER/Library/Developer/Shared/Documentation/DocSets/$COMPANY_RDOMAIN_PREFIX.$PRODUCT_NAME.docset\"" >> $TEMP_DIR/loadDocSet.scpt
echo "end tell" >> $TEMP_DIR/loadDocSet.scpt
# Run the load-docset applescript command.
osascript $TEMP_DIR/loadDocSet.scpt
exit 0
However, I am getting these errors
Osascript:/Users/[username]/SVN/trunk/Examples: No such file or directory
Earlier in the script output (in xcode window after building) I see these msgs:
Configuration file '/Users/[username]/SVN/trunk/Examples' created
the problem I think is that the full path is actually
'/Users/[username]/SVN/trunk/Examples using SDK'
I was working on the assumption that the whitespaces were the culprit. So I tried two approaches:
$SOURCE_ROOT = "/Users/[username]/SVN/trunk/Examples using SDK"
$SOURCE_ROOT = /Users/[username]/SVN/trunk/Examples\ using\ SDK
set $SOURCE_ROOT to quoted form of POSIX path of /Users/$USER/SVN/trunk/Examples\ using\ SDK/
but all give the same Osascript error as above. Also, the docset is not build into the requested directory
/Users/$USER/Library/Developer/Shared/Documentation/DocSets/$COMPANY_RDOMAIN_PREFIX.$PRODUCT_NAME.docset\
I've scratched my head over this for a while but can't figure out what is the problem. One hypothesis is that I am running Doxygen on a project that is not a new project. To handle this EXTRACT_ALL is set to YES (which should remove all warning messages, but I get 19 warnings too).
Any help would be much appreciated
thank you
Peyman
I suggest that you double quote "$SOURCE_ROOT" wherever you use it in your shell script.
Mouviciel....i figured it out....needed to put the whole variable in parenthesis i.e. $(SOURCE_ROOT).
thank you for your help

Resources