<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Bash – Yeri Tiete</title>
    <link>https://yeri.be/tag/bash/</link>
    <description>Yeri Tiete&#39;s blog</description>
    <language>en</language>
    <copyright>© Yeri Tiete</copyright>
    <lastBuildDate>Tue, 04 Jul 2023 15:20:06 +0200</lastBuildDate>
    <atom:link href="https://yeri.be/tag/bash/index.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>PoC: Betteruptime &#43; Python-kasa</title>
      <link>https://yeri.be/poc-betteruptime-python-kasa/</link>
      <pubDate>Tue, 04 Jul 2023 15:20:06 +0200</pubDate>
      <author>Yeri Tiete</author>
      <guid isPermaLink="true">https://yeri.be/poc-betteruptime-python-kasa/</guid><enclosure url="https://static.yeri.be/2023/07/kasa-smart-plug.jpg" length="0" type="image/jpeg" />
      <description>&lt;p&gt;&lt;strong&gt;Content Update&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;The provided scripts have been updated on 16 Jul 2023. Specifically the SmartStrip part was not working as intended. &lt;/p&gt;&#xA;&lt;hr class=&#34;wp-block-separator has-alpha-channel-opacity&#34;/&gt;&#xA;&lt;p&gt;I&#39;ve been a big fan of &lt;a rel=&#34;noreferrer noopener&#34; href=&#34;https://uptime.betterstack.com/&#34; target=&#34;_blank&#34;&gt;Betteruptime&lt;/a&gt;. I&#39;ve started using it to monitor all my assets online (websites, DNS, ping, successful script runs) as well as my servers (using &lt;a rel=&#34;noreferrer noopener&#34; href=&#34;https://betterstack.com/docs/uptime/cron-and-heartbeat-monitor/&#34; target=&#34;_blank&#34;&gt;heartbeats&lt;/a&gt;). &lt;/p&gt;&#xA;&lt;figure class=&#34;wp-block-image alignwide size-large&#34;&gt;&lt;a href=&#34;https://static.yeri.be/2023/07/mammoth.png&#34; target=&#34;_blank&#34; rel=&#34;noreferrer noopener&#34;&gt;&lt;img src=&#34;https://static.yeri.be/2023/07/mammoth-1024x570.png&#34; alt=&#34;Screenshot of Betteruptime showing a heartbeat that failed for several hours. &#34; class=&#34;wp-image-72880&#34;/&gt;&lt;/a&gt;&lt;figcaption class=&#34;wp-element-caption&#34;&gt;Image of a heartbeat that failed for several hours. After 2 hours of no hearbeat, it turned into an incident, and several hours later the heartbeats resumed. &lt;/figcaption&gt;&lt;/figure&gt;&#xA;&lt;p&gt;I have a few Raspberry Pi&#39;s, and once in a while they hang (not sure why, maybe USB-to-SSD issues or something). Nothing too critical, but annoying. &lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><img src="https://static.yeri.be/2023/07/kasa-smart-plug.jpg" alt="PoC: Betteruptime + Python-kasa"></p><p><strong>Content Update</strong></p>
<p>The provided scripts have been updated on 16 Jul 2023. Specifically the SmartStrip part was not working as intended. </p>
<hr class="wp-block-separator has-alpha-channel-opacity"/>
<p>I've been a big fan of <a rel="noreferrer noopener" href="https://uptime.betterstack.com/" target="_blank">Betteruptime</a>. I've started using it to monitor all my assets online (websites, DNS, ping, successful script runs) as well as my servers (using <a rel="noreferrer noopener" href="https://betterstack.com/docs/uptime/cron-and-heartbeat-monitor/" target="_blank">heartbeats</a>). </p>
<figure class="wp-block-image alignwide size-large"><a href="https://static.yeri.be/2023/07/mammoth.png" target="_blank" rel="noreferrer noopener"><img src="https://static.yeri.be/2023/07/mammoth-1024x570.png" alt="Screenshot of Betteruptime showing a heartbeat that failed for several hours. " class="wp-image-72880"/></a><figcaption class="wp-element-caption">Image of a heartbeat that failed for several hours. After 2 hours of no hearbeat, it turned into an incident, and several hours later the heartbeats resumed. </figcaption></figure>
<p>I have a few Raspberry Pi's, and once in a while they hang (not sure why, maybe USB-to-SSD issues or something). Nothing too critical, but annoying. </p>
<p>I've plugged them all on <a href="https://www.tp-link.com/sg/home-networking/smart-plug/" target="_blank" rel="noreferrer noopener">TP-Link Kasa</a> smart plugs to remotely restart them if I had to (once or twice a year). </p>
<pre class="wp-block-verse">Note, to confuse everyone, TP-Link also launched Tapo, which... competes with Kasa and is not compatible, but does the exact same thing... ¯\_(ツ)_/¯</pre>
<p>After some <a rel="noreferrer noopener" href="https://medium.com/geekculture/use-raspberry-pi-and-tp-link-kasa-to-automate-your-devices-9f936a6243c1" target="_blank">Googling</a> (actually <a href="https://kagi.com" target="_blank" rel="noreferrer noopener">Kagi'ing</a>) I found out, there's a <a rel="noreferrer noopener" href="https://python-kasa.readthedocs.io/en/latest/" target="_blank">Python library</a> that lets you control your smart plugs. </p>
<p>So, the idea was born to:</p>
<ul>
<li>Check Betteruptime heartbeats, if down, power cycle the smart plug</li>
<li>Do this at most once per day (in case something else is causing issues)</li>
<li>Betteruptime <a rel="noreferrer noopener" href="https://betterstack.com/docs/uptime/api/get-a-single-hearbeat/" target="_blank">heartbeats</a> manage when a device is marked as offline (i.e.: it expects a heartbeat every 5 minutes, but will only consider the device down if no heartbeats are received for 2 hours).  </li>
<li>The bulk of the code had to be written by ChatGPT. Let ChatGPT choose the language (it ended up being a mix of Bash and Python)</li>
<li>Everything needs to run in Docker (using a cron, the Docker container doesn't daemonise)</li>
<li>These run on Raspberry Pi's (but of course the RPi can't check itself: so RPi1 checks for RPi2, and vice versa. As these RPis are on different networks (my parent's home, my own home, etc) I had to enable "<code>--net=host</code>" in <code>Docker run</code> to get the correct routes from the host system, but you may not actually need this</li>
<li>To top if off, sent an email (using Mailgun EU servers) to warn me something broke and it rebooted</li>
</ul>
<p>So, after some fiddling (half an evening or so) the proof-of-concept worked. </p>
<p>I should probably throw this in a Git repo but shrug. I don't want to give the impression that I'll maintain this and provide support.  </p>
<p>Dockerfile:</p>
<pre class="wp-block-code"><code>FROM python:alpine
RUN apk add bash curl jq
RUN pip3 install python-kasa
COPY heartbeat.sh kasa-api.py /
VOLUME /tmp/kasa/
CMD &#91;"/heartbeat.sh"]</code></pre>
<p>Python script <code>kasa-api.py</code> (this works with both <a href="https://www.tp-link.com/sg/home-networking/smart-plug/kp303/" target="_blank" rel="noreferrer noopener">smart strips</a> and <a href="https://www.kasasmart.com/us/products/smart-plugs/kasa-smart-wifi-plug-hs100" target="_blank" rel="noreferrer noopener">smart plugs</a>):</p>
<pre class="wp-block-code"><code>import sys
import asyncio
from kasa import SmartPlug, SmartStrip

async def main():
	if len(sys.argv) != 4:
		print("Usage: python kasa-api.py type IP-address outlet-index")
		return

	device_type = sys.argv&#91;1]
	ip_address = sys.argv&#91;2]
	outlet_index = int(sys.argv&#91;3])

	if device_type == "smartplug":
		await control_smart_plug(ip_address)
	elif device_type == "smartstrip":
		await control_smart_strip(ip_address, outlet_index)
	else:
		print(f"Unsupported device type: {device_type}")

async def control_smart_plug(ip_address):
	plug = SmartPlug(ip_address)

	try:
		await plug.update()

		# Retrieve the current state
		plug_state = plug.is_on

		# Turn off the plug
		await plug.turn_off()

		print(f"Turned off SmartPlug at {ip_address}")
		await asyncio.sleep(5)

		# Turn on the plug if it was previously on
		if plug_state:
			await plug.turn_on()

		print(f"Turned on SmartPlug at {ip_address}")
	except Exception as e:
		print(f"Failed to control SmartPlug at {ip_address}: {e}")

async def control_smart_strip(ip_address, outlet_index):
	strip = SmartStrip(ip_address)

	try:
		await strip.update()

		# Retrieve the current state of the specified child plug
		child_state = strip.children&#91;outlet_index].is_on

		# Turn off the specified child plug
		await strip.children&#91;outlet_index].turn_off()

		print(f"Turned off child plug {outlet_index} in SmartStrip at {ip_address}")
		await asyncio.sleep(5)

		# Turn on the child plug if it was previously on
		await strip.children&#91;outlet_index].turn_on()

		print(f"Turned on child plug {outlet_index} in SmartStrip at {ip_address}")
	except Exception as e:
		print(f"Failed to control SmartStrip at {ip_address}: {e}")

# Run the asyncio event loop
asyncio.run(main())</code></pre>
<p><code>heartbeat.sh</code> -- with example devices. Be sure to fill in the variables (including <code>hb</code>, that's the heartbeat ID you can get from the Betteruptime URL and the IP or DNS hostname of the smartplug):</p>
<pre class="wp-block-code"><code>#!/bin/bash

API_KEY="BetterUptime API token"
BU="https://uptime.betterstack.com/api/v2/heartbeats/" # no need to change this

MAILGUN_API_KEY="Mailgun API token"
MAILGUN_DOMAIN="mg.you.com" # use your own domain

if &#91;&#91; "$DEVICE" = tyr ]] || &#91;&#91; "$1" = tyr ]]; then

	# Tyr
	device="Tyr"
	hb=1111
	bu="https://uptime.betterstack.com/team/1/heartbeats/$hb"
	plug_type="smartplug"
	plug_host="smartplug1.kasa.you.com"

elif &#91;&#91; "$DEVICE" = mammoth ]] || &#91;&#91; "$1" = mammoth ]]; then

	# Mammoth
	device="mammoth"
	hb=2222
	bu="https://uptime.betterstack.com/team/1/heartbeats/$hb"
	plug_type="smartstrip"
	plug_host="smartstrip1.kasa.you.com"
	plug_index=0 # plug 2 is rly plug 3 because the index counts from 0 to 2 and not from 1 to 3.

elif &#91;&#91; "$DEVICE" = liana ]] || &#91;&#91; "$1" = liana ]]; then

	# Liana
	device="liana"
	hb=3333
	bu="https://uptime.betterstack.com/team/1/heartbeats/$hb"
	plug_type="smartstrip"
	plug_host="smartstrip1.kasa.you.com"
	plug_index=1 # plug 2 is rly plug 3 because the index counts from 0 to 2 and not from 1 to 3.

elif &#91;&#91; "$DEVICE" = eagle ]] || &#91;&#91; "$1" = eagle ]]; then

	device="eagle"
	hb=4444
	bu="https://uptime.betterstack.com/team/1/heartbeats/$hb"
	plug_type="smartstrip"
	plug_host="smartstrip1.kasa.yeri.be"
	plug_index=2 # plug 2 is rly plug 3 because the index counts from 0 to 2 and not from 1 to 3.

else
	echo "Unknown device."
	exit 1
fi

url=$BU/$hb

send_alert() {
	MAILGUN_URL="https://api.eu.mailgun.net/v3/$MAILGUN_DOMAIN/messages"
	from="kasa@you.com"
	to="alert@you.com"
	subject="Smartplug power cycled: $device"
	body="rebooted device $device!"$'\n'"Kasa IP: $plug_host."$'\n'"$bu"

	# Send alert email
	curl -s --user "api:$MAILGUN_API_KEY" \
		"$MAILGUN_URL" \
		-F from="$from" \
		-F to="$to" \
		-F subject="$subject" \
		-F text="$body"
}

kasa_cycle() {
	echo "Betteruptime heartbeat ($hb) says the service for $device is down, restarting."
	python /kasa-api.py "$plug_type" "$plug_host" "$plug_index"
	# Update the last execution date in the file
	echo "$current_date" &gt; "$file"
}

kasa_info() {
	kasa --host $plug_host
}

response=$(curl -sL "$url" -H "Authorization: Bearer $API_KEY")
status=$(echo "$response" | jq -r '.data.attributes.status')

if &#91;&#91; "$status" == "down" ]]; then
	dir="/tmp/.kasa/"
	mkdir -p "$dir"
	file="${dir}${device}.txt"

	# Get current date
	current_date=$(date "+%F")
	# Check if the file exists
	if &#91; -f "$file" ]; then
		# Get last execution date from the file
		last_execution=$(cat "$file")
		# We only want to run this once every 24hrs. If a reboot doesn't fix it, something more
		# serious is going on and likely needs manual intervention. No point spam rebooting the device.
		if &#91;&#91; "$current_date" != "$last_execution" ]]; then
			kasa_cycle
			send_alert
		else
			echo "Power cycle already executed today."
		fi
	else
		kasa_cycle
		send_alert
	fi
elif &#91;&#91; "$status" == "up" ]]; then
	echo "Betteruptime heartbeat says the service ($hb) for $device is up."
else
	# this could happen if the heartbeat is paused.
	echo "Unknown status."
	kasa_info
	exit 1
fi</code></pre>
<p>I run Docker with two scripts, a builder (<code>rebuild.sh</code>) and a file that runs it (<code>start.sh</code>). It should rebuild in case a docker cleanup script ran (and deleted dangling containers). </p>
<p>I run this as <code>root</code> and probably shouldn't, but yeah... That'll be for another lifetime. </p>
<p>Be sure to change the paths (<code>/root/git/kasa-api</code>) in both scripts. </p>
<p><code>rebuild.sh</code>:</p>
<pre class="wp-block-code"><code>#!/bin/bash
cd /root/git/kasa-api # the path where this project exists

git pull &gt; /dev/null

BASEIMAGE=`cat Dockerfile | grep FROM | awk '{print $2}'`
docker pull $BASEIMAGE
docker build -q -t kasa-api .
rm -f /tmp/.kasa/*.txt</code></pre>
<p><code>start.sh</code>:</p>
<pre class="wp-block-code"><code>#!/bin/bash

if &#91; -z "$1" ]; then
	echo "Missing device name."
	exit 1
fi

docker stop kasa-api 2&gt; /dev/null
docker rm kasa-api 2&gt; /dev/null

run_kasa() {
	DEVICE=$1
	docker run --net=host -v /tmp/.kasa:/tmp/.kasa --rm -e DEVICE=$DEVICE --name kasa-api kasa-api
}

if &#91;&#91; $(docker image ls | grep kasa-api) ]]; then
	run_kasa $1
else
	cd /root/git/kasa-api
	/root/git/kasa-api/rebuild.sh &gt; /dev/null
	run_kasa $1
fi</code></pre>
<p>And that's pretty much it. I run this using with cron in <code>/etc/cron.d/</code>. For example (be sure to edit the parameter/device name/path):</p>
<pre class="wp-block-code"><code>#
# cron-jobs for kasa-api
#

MAILTO=root

*/15 * * * *	root	if &#91; -x /root/git/kasa-api/start.sh ] &amp;&amp; &#91; -f /root/git/kasa-api/start.sh ]; then /root/git/kasa-api/start.sh tyr &gt;/dev/null; fi</code></pre>
<p>I'm sure there must be bugs in this ChatGPT generated code but... so far, it has actually worked.</p>
]]></content:encoded>
      <category>hardware</category><category>linux</category><category>networking</category><category>software</category>
      <category>bash</category><category>dailyprompt</category><category>dailyprompt-2001</category><category>docker</category><category>python</category>
    </item>
    
    <item>
      <title>The single most useful thing in bash</title>
      <link>https://yeri.be/the-single-most-useful-thing-in-bash/</link>
      <pubDate>Sat, 20 Apr 2013 11:38:50 +0200</pubDate>
      <author>Yeri Tiete</author>
      <guid isPermaLink="true">https://yeri.be/the-single-most-useful-thing-in-bash/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://coderwall.com/p/oqtj8w&#34; target=&#34;_blank&#34;&gt;This&lt;/a&gt;.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><a href="https://coderwall.com/p/oqtj8w" target="_blank">This</a>.</p>
]]></content:encoded>
      <category>linux</category><category>software</category>
      <category>bash</category>
    </item>
    
    <item>
      <title>OpenVPN: Can&#39;t assign requested address</title>
      <link>https://yeri.be/openvpn-cant-assign-requested-address/</link>
      <pubDate>Tue, 12 Feb 2013 13:17:22 +0100</pubDate>
      <author>Yeri Tiete</author>
      <guid isPermaLink="true">https://yeri.be/openvpn-cant-assign-requested-address/</guid>
      <description>&lt;p&gt;For no clear reason, OpenVPN on Mac with Tunnelblick (any version, had this problem for a few years already) results in these kind of error messages (and refuses to connect):&lt;/p&gt;&#xA;&lt;pre&gt;2013-02-05 17:44:31 write UDPv4: Can&#39;t assign requested address (code=49)&#xA;2013-02-05 17:44:33 write UDPv4: Can&#39;t assign requested address (code=49)&lt;/pre&gt;&#xA;&lt;p&gt;This seems to appear more often when swapping WiFi/IP range (after my Mac goes into sleep). But also happens when connecting to the same WiFi. It doesn&amp;rsquo;t change anything whether I disconnect OpenVPN before putting the Mac to sleep.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>For no clear reason, OpenVPN on Mac with Tunnelblick (any version, had this problem for a few years already) results in these kind of error messages (and refuses to connect):</p>
<pre>2013-02-05 17:44:31 write UDPv4: Can't assign requested address (code=49)
2013-02-05 17:44:33 write UDPv4: Can't assign requested address (code=49)</pre>
<p>This seems to appear more often when swapping WiFi/IP range (after my Mac goes into sleep). But also happens when connecting to the same WiFi. It doesn&rsquo;t change anything whether I disconnect OpenVPN before putting the Mac to sleep.</p>
<p>The solution I&rsquo;ve found to solve this is:</p>
<ol>
	<li><span style="line-height: 13px;">Disconnect OpenVPN (via Tunnelblick)</span></li>
	<li>Turn off WiFi</li>
	<li>Run the script I've attached below (flush.sh)</li>
	<li>Fill in your admin/sudo password</li>
	<li>Hit ctrl+C if it doesn't exit instantly (happens in 99% of the cases)</li>
	<li>Run the script once or twice more to be sure, it will exit correctly this time</li>
	<li>Reconnect to the WiFi</li>
	<li>Reconnect OpenVPN (via Tunnelblick): this time it will work</li>
</ol>
The script (name it flush.sh, chmod +x, and run ./flush.sh via Terminal):
<p><span style="text-decoration: underline;">Edit</span>: updated script (29/01/2014)</p>
<pre>#!/bin/bash
# Change IFACE to match your WiFi interface 
# (en0 on Macbook Air and Retina, en1 on old Macbook Pros with ethernet) 
IFACE=en0
sudo ifconfig $IFACE down
sudo route flush
sudo ifconfig $IFACE up</pre>
<p>In case the script hangs (sometimes, route flush hangs): hit ctrl+C, and execute it again.</p>
]]></content:encoded>
      <category>apple</category><category>errors</category><category>linux</category><category>networking</category><category>software</category>
      <category>bash</category><category>openvpn</category>
    </item>
    
    <item>
      <title>Prowl: check server status (using ping)</title>
      <link>https://yeri.be/prowl-check-server-status-using-ping/</link>
      <pubDate>Sun, 30 Aug 2009 11:35:57 +0200</pubDate>
      <author>Yeri Tiete</author>
      <guid isPermaLink="true">https://yeri.be/prowl-check-server-status-using-ping/</guid>
      <description>&lt;p&gt;Yesterday I&amp;rsquo;ve start using &lt;a href=&#34;http://prowl.weks.net/&#34; target=&#34;_blank&#34;&gt;Prowl&lt;/a&gt;, as I heard good comments about it.  And one of the things I want it to check, are my server statuses.  I made a quick script using bash and crontab to check every 10 min if it replies on ping.  Per server, I created &amp;ldquo;host.domain.tld.sh&amp;rdquo; (e.g. zero.rootspirit.com.sh), and added this in the file:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-BASH&#34; data-lang=&#34;BASH&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#!/bin/bash&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;KEY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;YourApiKey&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;HOST&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;zero.rootspirit.com&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ping -c &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$HOST&lt;/span&gt;   &lt;span class=&#34;p&#34;&gt;&amp;amp;&lt;/span&gt;&amp;gt;/dev/null&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$?&lt;/span&gt; -ne &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;curl -k -s &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://prowl.weks.net/publicapi/add?apikey=&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$KEY&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;amp;application=Server%20Connectivity%20Failure&amp;amp;event=&amp;amp;description=&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$HOST&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;amp;priority=2&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Of course, change KEY to &lt;a href=&#34;https://prowl.weks.net/settings.php&#34; target=&#34;_blank&#34;&gt;your API&lt;/a&gt; key, HOST to the IP or DNS of the server it should ping.  Also, make sure, that when pinging on your host where you&amp;rsquo;ll run the bash script on, a non-existing domain actually returns:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Yesterday I&rsquo;ve start using <a href="http://prowl.weks.net/" target="_blank">Prowl</a>, as I heard good comments about it.  And one of the things I want it to check, are my server statuses.  I made a quick script using bash and crontab to check every 10 min if it replies on ping.  Per server, I created &ldquo;host.domain.tld.sh&rdquo; (e.g. zero.rootspirit.com.sh), and added this in the file:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-BASH" data-lang="BASH"><span class="line"><span class="cl"><span class="cp">#!/bin/bash
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="nv">KEY</span><span class="o">=</span>YourApiKey
</span></span><span class="line"><span class="cl"><span class="nv">HOST</span><span class="o">=</span>zero.rootspirit.com
</span></span><span class="line"><span class="cl">ping -c <span class="m">1</span> <span class="nv">$HOST</span>   <span class="p">&amp;</span>&gt;/dev/null
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[</span> <span class="nv">$?</span> -ne <span class="m">0</span> <span class="o">]</span> <span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">curl -k -s <span class="s2">&#34;https://prowl.weks.net/publicapi/add?apikey=</span><span class="nv">$KEY</span><span class="s2">&amp;application=Server%20Connectivity%20Failure&amp;event=&amp;description=</span><span class="nv">$HOST</span><span class="s2">&amp;priority=2&#34;</span>
</span></span><span class="line"><span class="cl"><span class="k">fi</span>
</span></span></code></pre></div><p>Of course, change KEY to <a href="https://prowl.weks.net/settings.php" target="_blank">your API</a> key, HOST to the IP or DNS of the server it should ping.  Also, make sure, that when pinging on your host where you&rsquo;ll run the bash script on, a non-existing domain actually returns:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-BASH" data-lang="BASH"><span class="line"><span class="cl">ping: unknown host ezfzigjagaqg.reg
</span></span></code></pre></div><p>instead of</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-BASH" data-lang="BASH"><span class="line"><span class="cl">PING ezfzigjagaqg.reg.rootspirit.com <span class="o">(</span>85.12.6.130<span class="o">)</span> 56<span class="o">(</span>84<span class="o">)</span> bytes of data.
</span></span></code></pre></div><p>(Should depend on the search line in /etc/resolv.conf)  As I&rsquo;m pinging about 6 servers I created the file &ldquo;checkServers.sh&rdquo; with this content:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-BASH" data-lang="BASH"><span class="line"><span class="cl"><span class="cp">#!/bin/bash
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="sb">`</span>/home/yeri/prowl/zero.rootspirit.com.sh <span class="p">&amp;</span>&gt;/dev/null<span class="sb">`</span>
</span></span><span class="line"><span class="cl"><span class="sb">`</span>/home/yeri/prowl/one.rootspirit.com.sh <span class="p">&amp;</span>&gt;/dev/null<span class="sb">`</span>
</span></span><span class="line"><span class="cl"><span class="sb">`</span>/home/yeri/prowl/two.rootspirit.com.sh <span class="p">&amp;</span>&gt;/dev/null<span class="sb">`</span>
</span></span><span class="line"><span class="cl"><span class="sb">`</span>/home/yeri/prowl/four.rootspirit.com.sh <span class="p">&amp;</span>&gt;/dev/null<span class="sb">`</span>
</span></span><span class="line"><span class="cl"><span class="sb">`</span>/home/yeri/prowl/vm0.rootspirit.com.sh <span class="p">&amp;</span>&gt;/dev/null<span class="sb">`</span>
</span></span><span class="line"><span class="cl"><span class="sb">`</span>/home/yeri/prowl/vm1.rootspirit.com.sh <span class="p">&amp;</span>&gt;/dev/null<span class="sb">`</span>
</span></span></code></pre></div><p>Make sure to chmod +x *.sh, to make it executable, and edit crontab and add something like that:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-BASH" data-lang="BASH"><span class="line"><span class="cl">*/10	*	*	*	*	/home/yeri/prowl/checkServers.sh <span class="p">&amp;</span>&gt;/dev/null
</span></span></code></pre></div><p>Don&rsquo;t forget to test it whether it works or not (try non-existing domain(s), and run the script again).</p>
]]></content:encoded>
      <category>apple</category><category>linux</category><category>networking</category><category>software</category>
      <category>bash</category><category>cron</category><category>crontab</category><category>iphone</category><category>prowl</category><category>server status</category>
    </item>
    
  </channel>
</rss>
