ActiveMQ command line: publish messages to a queue from a file? - bash

I have an app that uses ActiveMQ, and typically, I test it by using AMQ's web UI to send messages to queues that my software is consuming from.
I'd like to semi-automate this and was hoping AMQ's command line has the capability to send a message to a specific queue by either providing that message as text in the command invocation, or ideally, reading it out of a file.
Examples:
./activemq-send queue="my-queue" messageFile="~/someMessage.xml"
or:
./activemq-send queue="my-queue" message="<someXml>...</someXml>"
Is there any way to do this?

You could use the "A" utility to do this.
a -b tcp://somebroker:61616 -p #someMessage.xml my-queue
Disclaimer: I'm the author of A, wrote it once to do just this thing. There are other ways as well, such as the REST interface, a Groovy script and whatnot.

ActiveMQ has a REST interface that you can send messages to from the command line, using, for example, the curl utility.
Here is a script I wrote and use for this very purpose:
#!/bin/bash
#
#
# Sends a message to the message broker on localhost.
# Uses ActiveMQ's REST API and the curl utility.
#
if [ $# -lt 2 -o $# -gt 3 ] ; then
echo "Usage: msgSender (topic|queue) DESTINATION [ FILE ]"
echo " Ex: msgSender topic myTopic msg.json"
echo " Ex: msgSender topic myTopic <<< 'this is my message'"
exit 2
fi
UNAME=admin
PSWD=admin
TYPE=$1
DESTINATION=$2
FILE=$3
BHOST=${BROKER_HOST:-'localhost'}
BPORT=${BROKER_REST_PORT:-'8161'}
if [ -z "$FILE" -o "$FILE" = "-" ] ; then
# Get msg from stdin if no filename given
( echo -n "body=" ; cat ) \
| curl -u $UNAME:$PSWD --data-binary '#-' --proxy "" \
"http://$BHOST:$BPORT/api/message/$DESTINATION?type=$TYPE"
else
# Get msg from a file
if [ ! -r "$FILE" ] ; then
echo "File not found or not readable"
exit 2
fi
( echo -n "body=" ; cat $FILE ) \
| curl -u $UNAME:$PSWD --data-binary '#-' --proxy "" \
"http://$BHOST:$BPORT/api/message/$DESTINATION?type=$TYPE"
fi

Based on Rob Newton's answer this is what i'm using to post a file to a queue. I also post a custom property (which is not possible trough the activemq webconsole)
( echo -n "body=" ; cat file.xml ) | curl --data-binary '#-' -d "customProperty=value" "http://admin:admin#localhost:8161/api/message/$QueueName?type=$QueueType"

Related

Bash: using netcat to call a function "remotelly", even possible?

(I have been testing (trying) like a thousand posts like chats, web servers, server-clients for netcat, no luck so far, therefore thinking if is it possible at all)
Lets say I have a silly bash function that all that does is to reply you saying you hello and how long is your name, and a script, on interactive console input so users can fell good (./myScript.sh interactiveBash):
#!/bin/bash
responseTo(){
local output=$1
local input=$2
plentyOfThings="Hello $input, you name is ${#input} characters long, and youre gona have a great day"
##may take a while, on tests, up to 3-5 seconds
eval $output="'$plentyOfThings'"
}
if [ "${1}" == "interactiveBash" ]
then
echo -n "What's you name? "
while read; do
response=""
responseTo response ${REPLY}
echo "··························· ${response}"
echo -ne "\nWhat's you name? "
done
fi
Cool, I run in a terminal, user can put his name, and terminal say hello and wish them a great day
now, becouse how that pretty complex function (responseTo) count the lenght of the name is pretty secret, need to be on a remote computer
so I tought to extend my scritp with (./myScript.sh onlineNetcatServer):
if [ "${1}" == "onlineNetcatServer" ]
then
my_port=8080
echo "Listening at ${my_ip}, and aying hello"
while true; do
nc -kl ${my_port} -w 0 \
0< < .... \
1> > .... \
2> .... #errors
....
echo "${_input} was here on IP ${_IP} and I told him ${_resposne}"
done
fi
and then give user the following script (./myScript.sh 192.168.1.42)
remome_ip=${1}
remote_port=8080
echo -n "What's you name? "
while read; do
response=""
nc -kl ${remome_ip} ${remote_port} -w 0 \
0< < ....${REPLY}.... \
1> > ....${response}.... \
2> .... #errors
....
echo "··························· ${response}"
done
sure, all comands in betwwen dots are missing, and no idea how to continue
(like the server will "serve" multiple clients, the netcat session need to be closed as soon as response is given, and preferiable, keep other waiting until served)
is that even possible with this estructure / usage of NetCat ??

How can i add break line in curl with json data?

I am using this bash script to post a new message to my rocket.chat instance.
#!/usr/bin/env bash
function usage {
programName=$0
echo "description: use this program to post messages to Rocket.chat channel"
echo "usage: $programName [-b \"message body\"] [-u \"rocket.chat url\"]"
echo " -b The message body"
echo " -u The rocket.chat hook url to post to"
exit 1
}
while getopts ":b:u:h" opt; do
case ${opt} in
u) rocketUrl="$OPTARG"
;;
b) msgBody="$OPTARG"
;;
h) usage
;;
\?) echo "Invalid option -$OPTARG" >&2
;;
esac
done
if [[ ! "${rocketUrl}" || ! "${msgBody}" ]]; then
echo "all arguments are required"
usage
fi
read -d '' payLoad << EOF
{"text": "${msgBody}"}
EOF
echo $payLoad
statusCode=$(curl \
--write-out %{http_code} \
--silent \
--output /dev/null \
-X POST \
-H 'Content-type: application/json' \
--data "${payLoad}" ${rocketUrl})
echo ${statusCode}
Everthings works fine, so i can send a new message like this
./postToRocket.sh -b "Hello from here" -u $RocketURL
But when i try to add a message with multiple lines like this
./postToRocket.sh -b "Hello from here\nThis is a new line" -u $RocketURL
it doesn't work. I get the following output:
{"text": "Hello from heren New Line"}
200
So what do i need to change, to use break line with these bash script. Any ideas?
First, the thing making the backslash in your \n disappear was the lack of the -r argument to read. Making it read -r -d '' payLoad will fix that. However, that's not a good solution: It requires your callers to pass strings already escaped for inclusion in JSON, instead of letting them pass any/every possible string.
To make valid JSON with an arbitrary string -- including one that can contain newline literals, quotes, backslashes, or other content that has to be escaped -- use jq:
payLoad=$(jq -n --arg msgBody "$msgBody" '{"text": $msgBody}')
...and then, after doing that, amend your calling convention:
./postToRocket.sh -b $'Hello from here\nThis is a new line' -u "$RocketURL"
I believe this has already been answered in SO here
Should work by adding the $ sign and using single quotes:
./postToRocket.sh -b $'Hello from here\nThis is a new line' -u $RocketURL

Using mosquitto in a shell script using a pipe

I'm using mosquitto on an openWRT device to receive some data from a server and then send this same data to a local printer to print this data.
I'm using this script to receive the data
mosquitto_sub -h "${HOST}" -k 30 -c -p 8883 -t "${TOPIC}" -u "${USERNAME}" -P "${PASSWORD}" --id "${ID}" | /bin/sh /bin/printer_execute "${TOPIC}" "${PRINTER}" "${USERNAME}" "${PASSWORD}"
And the printer_execute code:
#!/bin/sh
TOPIC="${1}"
PRINTER="${2}"
USERNAME="${3}"
PASSWORD="${4}"
while read MSG
do
echo "input: ${MSG}"
echo "INPUT MSG: " "${MSG}" >> /root/log
RES=`curl -m 2 --header "Content-Type: text/xml;charset=UTF-8" --header "SOAPAction: ''" --header "If-Modified-Since: Thu, 01 Jan 1970 00:00:00 GMT" --data "${MSG}" "http://${PRINTER}/cgi-bin/epos/service.cgi?devid=local_printer&timeout=5000"`
mosquitto_pub -h ${HOST_PLACEHOLDER} -p 8883 -t "${TOPIC}-response" -m "${RES}" -u "${USERNAME}" -P "${PASSWORD}"
echo "RESULT CURL: " "${RES}" >> /root/log
done
This solution works with a relatively low messages per second, but when the volume is too high the printer_execute code stop working. I'm pretty new to shell scripting and I guess the problem could be caused by the pipe and while read pattern or by the while exit condition, but i'm not really sure.
Anyone has some idea or found a similar problem and know how to solve this?
EDIT:
In light of the answers i have tried to do this:
EDIT2: Sorry in the first edit i just added what i modified but the entire script is like that and the scope should be correct for the variables.
#!/bin/sh
TOPIC="${1}"
PRINTER="${2}"
USERNAME="${3}"
PASSWORD="${4}"
PrintOne(){
MSG="${1}"
RES=$(curl [params])
mosquitto_pub -h [host] -p 8883 -d -t "${TOPIC}-response" -m "${RES}" -u "${USERNAME}" -P "${PASSWORD}"
echo "RESULT CURL: " "${RES}" >> /root/log
}
while read msg ; do
PrintOne "$msg" &
done
With the printone and the appersand this take one message and stop working, without the & it's just like it was before.
You could try making a function to handle one message and calling that in the background (by appending an ampersand) so that you can respond quickly and in parallel - and that will allow you to take longer to handle each message... for a period. If your messages continually arrive faster than you can handle them, there will inevitably be a backlog.
Something like this:
#!/bin/bash
PrintOne(){
echo "Received $1"
curl ...
mosquitto_pub ...
echo $RESULT
}
while read msg ; do
PrintOne "$msg" &
done
If you want a little example. change the code to this and save it as go, and make it executable with chmod +x go
#!/bin/bash
PrintOne(){
echo "Received $1"
sleep 2
echo "Finished $1"
}
while read msg ; do
PrintOne "$msg" &
done
Now send it 10 lines:
seq 10 | ./go
Then remove the ampersand, and do exactly the same thing again and you will see the difference.
A more complete version of my answer is as follows:
#!/bin/bash
PrintOne(){
TOPIC="${1}"
PRINTER="${2}"
USERNAME="${3}"
PASSWORD="${4}"
curl ...
mosquitto_pub ...
echo $RESULT
}
while read msg ; do
PrintOne "${1}" "${2}" "${3}" "${4}" &
done

How to get success count, failure count and failure reason when testing rest webservices from file using shell script

Hi i am testing web services using shell script by having multiple if condition, with the shell script coding i am getting success count, failure count and failure reason
success=0
failure=0
if curl -s --head --request DELETE http://localhost/bimws/delete/deleteUser?email=pradeepkumarhe1989#gmail.com | grep "200 OK" > /dev/null; then
success=$((success+1))
else
echo "DeleteUser is not working"$'\r' >> serverLog.txt
failure=$((failure+1))
fi
if curl -s --head --request GET http://localhost/bimws/get/getUserDetails?email=anusha4saju#gmail.com | grep "200 OK" > /dev/null; then
success=$((success+1))
else
curl -s --head --request GET http://localhost/bimws/get/getUserDetails?email=anusha4saju#gmail.com > f1.txt
echo "getUserDetails is not working"$'\r' >> serverLog.txt
failure=$((failure+1))
fi
if curl -s -i -X POST -H "Content-Type:application/json" http://localhost/bimws/post/addProjectLocationAddress -d '{"companyid":"10","projectid":"200","addresstypeid":"5","address":"1234 main st","city":"san jose","state":"CA","zip":"989898","country":"United States"}' | grep "200 OK" > /dev/null; then
success=$((success+1))
else
echo "addProjectLocationAddress is not working"$'\r' >> serverLog.txt
failure=$((failure+1))
fi
echo $success Success
echo $failure failure
but i am looking forward to test the web services from a file like i have file called web_services.txt which contains all my web services using shell script how do i execute and success count, failure count and failure reason
web_services.txt
All are different calls delete,get and post
http://localhost/bimws/delete/deleteUser?email=pradeepkumarhe1989#gmail.com
http://localhost/bimws/get/getUserDetails?email=anusha4saju#gmail.com
http://localhost/bimws/post/addProjectLocationAddress -d '{"companyid":"10","projectid":"200","addresstypeid":"5","address":"1234 main st"
,"city":"san jose","state":"CA","zip":"989898","country":"United States"}'
First of all, your current code does not correctly deal with empty lines. You need to skip those.
Your lines already contain shell commands. Running curl on them makes no sense. Instead, you should evaluate these commands.
Then, you need to modify curl so that it reports whether the request was successful by adding -f:
FILE=D:/WS.txt
success=0
failure=0
while read LINE; do
if test -z "$LINE"; then
continue
fi
if eval $(echo "$LINE" | sed 's/^curl/curl -f -s/') > /dev/null; then
success=$((success+1))
else
echo $LINE >> aNewFile.txt
failure=$((failure+1))
fi
done < $FILE
echo $success Success
echo $failure failure

Assign variable and redirect in bash

I'm doing ad-hoc profiling on a web service that seems to maintain some state and get slower and slower until eventually things start timing out. I have a simple script that will expose this behavior:
while true
do
RESPONSE_CODE=$( curl --config curl.config )
if [ "$RESPONSE_CODE" -eq "200" ]; then
echo SUCCESS
else
echo FAILURE
fi
done
Along with some headers, cookies, post data, url, etc. curl.config in particular has the lines:
silent
output = /dev/null
write-out = "%{http_code}"
So the only output from curl should be the HTTP status code.
This works fine. What I'd like to do is something like this:
{ time -p RESPONSE_CODE=$(curl --config curl.config) ; } 2>&1 | awk '/real/{print $2;}'
to get a running printout of how long these queries actually take, while still saving curl's output for use in my test. But that doesn't work.
How can I capture the http status from curl AND grab the output of time so I can process both?
As written:
RESPONSE_CODE = $( curl --config curl.config )
you have spaces around the assignment which simply does not work in shell (it tries to execute a command RESPONSE_CODE with = as the first argument, etc. You need:
RESPONSE_CODE=$( curl --config curl.config )
The time built-in is hard to redirect. Since you need both HTTP status and real time, you will have to do something to capture both values. One possibility is:
set -- $( (time -p -- curl --config curl.config ) 2>&1 |
awk '/real/{print $2} /^[0-9]+$/{print}')
which will set $1 and $2. Another is array assignment:
data=( $( (time -p -- curl --config curl.config ) 2>&1 |
awk '/real/{print $2} /^[0-9]+$/{print}') )
The HTTP response code should appear before the time.
(Tested using sh -c 'echo 200; sleep 1' in lieu of curl --config curl.config.)
This should work if Curl's response is only a single line:
#!/bin/bash
RESPONSE_CODE=''
TIME=''
while read -r TYPE DATA; do
case "$TYPE" in
curl)
RESPONSE_CODE=$DATA
;;
real)
TIME=$DATA
;;
esac
done < <(exec 2>&1; time -p R=$(curl --config curl.config); echo "curl $R")
Or use an associative array:
#!/bin/bash
declare -A RESPONSE
while read -r TYPE DATA; do
RESPONSE[$TYPE]=$DATA
done < <(exec 2>&1; time -p R=$(curl ...); echo "code $R")
echo "${RESPONSE[code] ${RESPONSE[real]}"

Resources