Create a command line script - shell

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.

Related

Terraform GCP Instance Metadata Startup Script Issue

I've been working with Terraform, v0.15.4, for a few weeks now, and have gotten to grips with most of the lingo. I'm currently trying to create a cluster of RHEL 7 instances dynamically on GCP, and have, for the most part, got it to run okay.
I'm at the point of deploying an instance with certain metadata passed along to it for use in scripts built into the machine image for configuration thereafter. This metadata is typically just passed via an echo into a text file, which the scripts then pickup as required.
It's... very simple. Echo "STUFF" > file... Alas, I am hitting the same issue OVER AND OVER and it's driving me INSANE. I've Google'd around for ages, but all I can find is examples of the exact thing that I'm doing, the only difference is that theirs works, mine doesn't... So hopefully I can get some help here.
My 'makes it half-way' code is as follows:
resource "google_compute_instance" "GP_Master_Node" {
...
metadata_startup_script = <<-EOF
echo "hello
you" > /test.txt
echo "help
me" > /test2.txt
EOF
Now the instance with this does create successfully, although when I look onto the instance, I get one file called ' /test.txt? ' (or if I 'ls' the file, it shows as ' /test.txt^M ') and no second file.. I can run any command instead of echo, and whilst the first finishes, the second+ does not. Why?? What on earth is causing that??
The following code I found also, but it doesn't work for me at all, with the error, 'Blocks of type "metadata" are not expected here.'
resource "google_compute_instance" "GP_Master_Node" {
...
metadata {
startup-script = "echo test > /test.txt"
}
Okaaaaay! Simple answer for a, in hindsight, silly question (sort of). The file was somehow formmated in DOS, meaning the script required a line continuation character to run correctly (specifically \ at the end of each individual command). Code as follows:
resource "google_compute_instance" "GP_Master_Node" {
...
metadata_startup_script = <<-EOF
echo "hello
you" > /test.txt \
echo "help
me" > /test2.txt \
echo "example1" > /test3.txt \
echo "and so on..." > /final.txt
EOF
However, what also fixed my issue was just 'refreshing' the file (probably a word for this, I don't know). I created a brand new file using touch, 'more'd the original file contents to screen, and then copy pasted them into the new one. On save, it is no longer DOS, as expected, and then when I run terraform the code runs as expected without requiring the line continuation characters at the end of commands.
Thank you to commentors for the help :)

Dynamically getting Properties in shell script

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

URL 404 Checker for bash

I want to write some code i can run in the bash that takes a list of URL's and checks if they return a 404. If the site is not returning a 404 i need the url to be written to the output list.
So in the end i should have a list with working sites.
I do not know how to realize the code.
This looks like something that could work right?:
How to check if a URL exists or returns 404 with Java?
You can use this code and build on it as necessary:
#!/bin/bash
array=( "http://www.stackoverflow.com" "http://www.google.com" )
for url in "${array[#]}"
do
if ! curl -s --head --request GET ${url} | grep "404 Not Found" > /dev/null
then
echo "Output URL not returning 404 ${url}"
fi
done
Thanks for your help. I found a package for linux called linkchecker. It does exactly what i want.

Is it possible to set curl to show file name before progress bar?

I'm trying to use curl in a script I'm developing that will download a bunch of files. I used -# switch with curl to force showing progress bar instead of full details which are not of interest. However, the output looks something like that:
######################################################################## 100.0%
######################################################################## 100.0%
######################################################################## 100.0%
This is not descriptive at all and I thought of adding a line before any download to show what is going to be downloaded but I did not like the result. I'm asking if there is a way for curl to output something like what we get from wget:
file1.zip 100%[=============================>] 33.05K --.-KB/s in 0.1s
file2.zip 100%[=============================>] 46.26K --.-KB/s in 0.1s
file3.zip 100%[=============================>] 19.46K --.-KB/s in 0.1s
I don't want to use wget instead, though, as it is not available for OS X by default and will require whoever going to use my script to install wget first using port or other methods which is inconvenient.
I found a good way to solve this by using curl-progress script here (https://gist.github.com/sstephenson/4587282) which wraps curl with a custom-drawn progress bar.
By default, the script curl-progress does not show file name in front of the progress bar but it is totally customisable. I had to modify print_progress function so it use one additional argument which is the name of the file to be downloaded. Therefor, I modified the printf statement inside print_progress so it print the file name in suitable location before the progress bar:
print_progress() {
local bytes="$1"
local length="$2"
local fileName="$3" # I added this third variable
...
...
printf "\x1B[0G %-10s%-6s\x1B[7m%*s\x1B[0m%*s\x1B[1D" \
"$fileName" "${percent}%" "$on" "" "$off" "" >&4
}
Now print_progress method expect three arguments and for that I modified the call to print_progress to send the third argument:
print_progress "$bytes" "$length" "$2"
Where $2 refers to the second argument sent to curl-progress. Now this is an example to download an arbitrary file from the web:
$ ./curl-progress -so "file1.zip" "http://download.thinkbroadband.com/20MB.zip"
And this is the output:
I will still have to ship a copy of curl-progress script along with mine but it is better than asking the user to install wget first.
For the particular case where curl is used to download only 1 file like given in examples in this thread, we could use this one liner function.
# Usage : curlp URL
curlp(){ f=${1##*/};printf "%28s%s" "" $f;COLUMNS=27 curl -# $1 -o $f ; }
It provide a progress bar with 20 # (i.e a # every 5% progress). You can indeed hack it to add more options, may be 2 args one is the URL the second could be the local name., etc...

Simulating sendmail with dummy script

I created a small shell script which logs all of it's input to a log file, with which I had thought I could replace the sendmail binary and thus achieve a simple way to simulate e-mail delivery without actually setting up a working sendmail.
This failed, however. For reasons I cannot understand.
I've looked at the PHP mail.c source and as far as I can understand (mind you, I'm not very experienced in C), PHP executes and talks directly to the binary (set in sendmail_path). But no log files are being created when I replace the sendmail binary with my script and the script replacing sendmail will always create a log file when it's executed, regardless of if there's input present or not.
The script itself works fine. Its' return codes should conform to that of sendmail's. With the difference that my script always returns 0, regardless of the input, since I'm not really interested in checking if the input is valid - just that I'm getting some.
Is it possible to achieve what I want, i.e. using a sendmail simulator?
The script source is provided below:
#!/bin/bash
LOGDIR=/tmp/sendmail-sim
NOW=$(date +%Y%m%dT%H%M)
CNT=1
FILENAME="$LOGDIR/$NOW.$CNT.log"
while [ -f $FILENAME ]; do
CNT=$(($CNT + 1))
FILENAME="$LOGDIR/$NOW.$CNT.log"
done
echo "$0 $*" > $FILENAME
while read BUF
do
echo $BUF >> $FILENAME
done
exit 0
PS. My current sendmail (or actually, postfix) does receive email from PHP, but I don't want to actually send any email or need to go digging in its' mail queue in development.
The problem was User Error, as usually. So, boys and girls, don't forget to check write permissions on all the relevant folders.
I've used Fakemail for this purpose in the past. It accepts SMTP connections but writes all mail to files rather than sending them along as email. There are both python and perl implementations.
http://www.lastcraft.com/fakemail.php
We setup apache to serve the directory that Fakemail was writing to. That was a quick and easy way for staff to view the messages that Fakemail was receiving and review for content, destination, etc. Formatting of HTML emails was a bit whacky for various reasons, so it was not so useful for vetting formatting of html emails.
If you need to to test you PHP application's ability to properly format and send email without actually sending them, I suggest you use the Pear Mail package. Fiddling with your system is not a good idea.
If you use Mail from Pear you could switch from sendmail to smtp to a mock implementation of the mail interface by changing the driver from 'sendmail' or 'smtp' to 'mock'.
http://pear.php.net/package/Mail/docs/latest/Mail/Mail.html
http://pear.php.net/package/Mail/docs/latest/Mail/Mail_mock.html
If your code looks like this:
mail('me#example.com', 'My Subject', $message);
Then change it to be testable using PEAR Mail:
include('Mail.php');
function sendEmail($recipient, $subject, $body, $driver = 'mail') {
$m = Mail::factory("mail");
$headers = array(
"From"=>"me#example.com",
"To" => $recipient,
"Subject"=> $subject);
$m->send($recipient, $headers, $body);
return $m;
}
// In Production:
sendEmail('me#example.com', 'My Subject', $message);
// During testing:
$m = sendEmail('me#example.com', 'My Subject', $message, 'mock');
var_dump($m->sentMessages);
This is very crude, since you should be using PHPUnit or SimpleTest, but this is a topic for another time and place :)
A note, if you just want to grab stdin and write it into a file, you don't need to loop one line at a time: you can write
cat - >> $FILENAME

Resources