How can I run multiple inotifywait loops in Bash? - bash

I have a script that ran as a daemon listening to a file:
#!/bin/bash
echo '1'
while inotifywait -e close_write /home/homeassistant/.homeassistant/automations.yaml
do
echo 'automations'
curl -X POST -H "x-ha-access: pass" -H "Content-Type: application/json" http://hassbian.local:8123/api/services/automation/reload
done;
I wanted to listen to several files, and tried adding two more loops:
while inotifywait -e close_write /home/homeassistant/.homeassistant/groups.yaml
do
echo 'gropus'
curl -X POST -H "x-ha-access: pass" -H "Content-Type: application/json" http://hassbian.local:8123/api/services/group/reload
done;
while inotifywait -e close_write /home/homeassistant/.homeassistant/core.yaml
do
echo 'core'
curl -X POST -H "x-ha-access: pass" -H "Content-Type: application/json" http://hassbian.local:8123/api/services/homeassistant/reload_core_config
done;
I realized that the first loop never gets closed so the other ones never get started, but not sure how I should solve this.

You need to run the first loop in a background process so that it doesn't block your script. You may want to run each loop in the background for symmetry, then wait on them at the end of the script.
while inotifywait -e close_write /home/homeassistant/.homeassistant/groups.yaml
do
echo 'gropus'
curl -X POST -H "x-ha-access: pass" -H "Content-Type: application/json" http://hassbian.local:8123/api/services/group/reload
done &
while inotifywait -e close_write /home/homeassistant/.homeassistant/core.yaml
do
echo 'core'
curl -X POST -H "x-ha-access: pass" -H "Content-Type: application/json" http://hassbian.local:8123/api/services/homeassistant/reload_core_config
done &
wait
However, you can run inotifywait in monitor mode and monitor multiple files, piping its output into a single loop. (Caveat: like any line-oriented output format, this cannot cope with filenames containing newlines. See the --format and --csv options for dealing with filenames containing whitespace.)
files=(
/home/homeassistant/.homeassistant/groups.yaml
/home/homeassistant/.homeassistant/core.yaml
)
take_action () {
echo "$1"
curl -X POST "x-ha-access: pass" -H "Content-Type: application/json" \
http://hassbian.local:8123/api/services/"$2"
}
inotifywait -m -e close_write "${files[#]}" |
while IFS= read -r fname _; do
case $fname in
*/groups.yaml) take_action "groups" "group/reload" ;;
*/core.yaml) take_action "core" "homeassistant/reload_core_config" ;;
sac
done

Related

BASH SCRIPT output doesn't export in file

i just stuck with my self coded application calling ws command (web socket) and i'm trying to export the output. Also i want to exit wscat when it's finished after sometime of input from API from the JSON backend devlopment
#!/bin/bash
while getopts a:c: flag
do
case "${flag}" in
a) accesskey=${OPTARG};;
c) clientnodeid=${OPTARG};;
esac
done
master="wscat -c ws://localhost:8091/ws/callback -H accessKey:$accesskey -H clientNodeId:$clientnodeid"
sleep 15
eval $master
final=$(eval echo "$master")
echo $final >>logfile.log
ps -ef | grep wscat | grep -v grep | awk '{print $2}' | xargs kill
#curl -X POST --data "$final" -k "https://localhost:7460/activate" -H "accept: application/json" -H "accessKey:$accesskey" -H "clientNodeId:$clientnodeid" -H "Content-Type: application/json" -H "callbackRequested:true"
exit
I want to call then output from wscat to sent over curl
When i run the script manually it got success but when i call it from another application (java) it's it running but not generating log.
With all words, i want to export $final to text file and that text file i should import it to --data of curl calling
Fixed based on #Barmar's comment:
You're overcomplicating this with all those variables. Just do
eval "$master" >> logfile.log

Using Bash to make a POST request

I have a 100 Jetpacks that I have to sign in to configure. I am trying to do it in a bash script but I am having no luck. I can connect to the wifi no problem but my POST request are not achieving anything. Any Advice? Here is link to my github. I have copies of what I captured on Burp suite https://github.com/Jdelgado89/post_Script
TYIA
#!/bin/bash
nmcli device wifi rescan
nmcli device wifi list
echo "What's they last four?"
read last4
echo "What's the Key?"
read key
nmcli device wifi connect Ellipsis\ \Jetpack\ $last4 password $key
echo "{"Command":"SignIn","Password":"$key"}" > sign_on.json
echo "{"CurrentPassword":"$key","NewPassword":"G1l4River4dm1n","SecurityQuestion":"NameOfStreet","SecurityAnswer":"Allison"}" > change_admin.json
echo "{"SSID":"GRTI Jetpack","WiFiPassword":"G1l4River3r","WiFiMode":0,"WiFiAuthentication":6,"WiFiEncription":4,"WiFiChannel":0,"MaxConnectedDevice":8,"PrivacySeparator":false,"WMM":true,"Command":"SetWifiSetting"}" > wifi.json
cat sign_on.json
cat change_admin.json
cat wifi.json
sleep 5
curl -X POST -H "Cookie: jetpack=6af5e293139d989bdcfd66257b4f5327" -H "Content-Type: application/json" -d #sign_on.json http://192.168.1.1/cgi-bin/sign_in.cgi
sleep 5
curl -X POST -H "Cookie: jetpack=6af5e293139d989bdcfd66257b4f5327" -H "Content-Type: application/json" -d #change_admin.json http://192.168.1.1/cgi-bin/settings_admin_password.cgi
sleep 5
curl -X POST -H "Cookie: jetpack=6af5e293139d989bdcfd66257b4f5327" -H "Content-Type: application/json" -d #wifi.json http://192.168.1.1/cgi-bin/settings_admin_password.cgi
This is not correct:
echo "{"Command":"SignIn","Password":"$key"}" > sign_on.json
The double quotes are not being put literally into the file, they're just terminating the shell string beginning with the previous double quote. So this is writing
{Command:SignIn,Password:keyvalue}
into the file, with no double quotes. You need to escape the nested double quotes.
echo "{\"Command\":\"SignIn\",\"Password\":\"$key\"}" > sign_on.json
However, it would be best if you used the jq utility instead of formatting JSON by hand. See Create JSON file using jq.
jq -nc --arg key "$key" '{"Command":"SignIn","Password":$key}' >sign_on.json

Bash script to loop through remote directory and pipe files 1 at a time to CURL

I am trying to transfer all files residing in a specified directory on Server1 to Server3 via a script running on Server2.
The transfer to Server3 has to happen through an API and thus must use the following CURL call:
curl -X POST https://content.dropboxapi.com/2/files/upload \
--header "Authorization: Bearer $token" \
--header "Dropbox-API-Arg: {\"path\": \"/xfer/$name\",\"mode\": \"add\",\"autorename\": true,\"mute\": false,\"strict_conflict\": false}" \
--header "Content-Type: application/octet-stream" \
--data-binary #$f
If it is just 1 file, I can do it successfully, but i'm trying to iterate through the directory on Server1 and send the file directly to the CURL call. So far I've got:
files="( $(ssh me#server1 ls dir/*) )"
while read f
do
name=$(basename ${f})
curl -X POST https://content.dropboxapi.com/2/files/upload \
--header "Authorization: Bearer $token" \
--header "Dropbox-API-Arg: {\"path\": \"/xfer/$name\",\"mode\": \"add\",\"autorename\": true,\"mute\": false,\"strict_conflict\": false}" \
--header "Content-Type: application/octet-stream" \
--data-binary #$f
done <<< "$files"
The loop seems to be reading the "(" from the array of files into the 1st file name, which obviously causes a problem. I can't get beyond that to be able to tell if POSTING the current file in the loop via --data-binary will actually do what I think (or am hoping) it will.
Any ieas?
The error in the original message was enclosing the ssh command with "()". I am working on a similar issue. In the past I've used Rsync but I want a solution that doesn't require installing extra software. Here is an example that I'm working with to move files off of a Nodejs dev server to backup, running in Bash on Debian:
files=$(ssh chris#estack ls ~/tmp/gateway)
#echo $files
for FILE in $files
do
if [[ "$FILE" = "node_modules" || "$FILE" = ".git" ]]
then
echo "skip $FILE";
continue
fi
echo Copy ~/tmp/gateway/$FILE
#scp -Cpr chris#estack:~/tmp/gateway/$FILE ~/tmp/tmp
done

curl PUT using auth token header to mesosphere fails without eval

EDIT:
I have managed to make it work with
response=$(
curl -k -X PUT -d "$marathon_payload" --write-out %{http_code} --silent --output "$tmp"\
-H "Authorization: token=$dcos_token" -H "$header_content_type" $app_id_url
)
The single quotes were causing the problem. It took a few gyrations but all good.
MORAL: quotes inside the value don't matter if the value is properly quoted UNLESS you eval the whole thing, and I should have known that. Occam's wins again.
end edit
I am initiating Mesosphere microservice deployments with curl, but it won't succeed without using eval. Since I recently inherited this code I've been trying to scrub the eval out of it just as a matter of habit, but it's thwarting me.
The script initiates the deployment with
response=$(
eval curl -k -X PUT -d "'$marathon_payload'" --write-out %{http_code} --silent --output $tmp\
-H "'Authorization: token=$dcos_token'" -H "'$header_content_type'" $app_id_url
)
If it gets a 200 or a 201, it loops a curl to effectively screen-scrape the deployments page till the request disappears.
chkDeploy() { rm -f $tmp;
eval curl -k -X GET --silent --write-out %{http_code} --silent --output $tmp\
-H "'Authorization: token=$dcos_token'" -H "'$header_content_type'" $deployments_url
}
response=$( chkDeploy )
$dcos_token is a base64 encoded string.
It then checks the service with another curl loop to the info page so it can verify the version number. This one is working fine with no eval.
chkCode() {
curl -k -X GET --write-out %{http_code} --silent --output $tmp $info_url;
}
response=$( chkCode )
The first two return 401, authentication failure.
I'm guessing the auth token quoting is off.
There's no reason to use eval here; you just need to quote the arguments to -H properly.
response=$(
curl -k -X PUT -d "$marathon_payload" \
--write-out %{http_code} \
--silent --output "$tmp" \
-H "Authorization: token=$dcos_token" \
-H "$header_content_type" "$app_id_url"
)

Start multiple background jobs and print results sequentially

I want to start a number of parallel jobs and I want the result outputs in sequential order. The jobs in my case are HTTP requests sent with curl and I'm interested in the response code only. Here is what I have so far:
for i in {1..6}
do
curl -H "Content-Type: application/json" -X POST \
-d 'some data' \
-s -o /dev/null -w "%{http_code}\n" \
<url of service> &
done
wait
This prints the result code of each request, but not in the correct order. Any way I can correct the order of the output?
It is necessary that the requests are actually sent in parallel.
Store the results to files, then print them out once everything is complete:
for i in {1..6}
do
curl -H "Content-Type: application/json" -X POST \
-d 'some data' \
-s -o /dev/null -w "%{http_code}\n" \
<url of service> > result_$i &
done
wait
for i in {1..6}
do
cat result_$i
rm result_$i
done

Resources