How to send message to CloudWatch when script has an error
Getting ready
- trapping signals
Signals are a limited form of inter-process communication (IPC), typically used in Unix, Unix-like, and other POSIX-compliant operating systems. A signal is an asynchronous notification sent to a process or to a specific thread within the same process in order to notify it of an event that occurred.
You can list all the signals by kill -l
or trap -l
command and it will print the signal number and name.
For example, when you press Ctrl+c
, the process will receive 2)SIGINT
signal.
We can trap these signals and assign the handler to it.
trap commands signals
For example:
#!/bin/bashtrap 'echo "Receive SIGINT"' INTwhile true;
do
echo "Process ID: $$"
sleep 1
done;
Run this script and press Ctrl+C
, it will showReceive SIGINT
in the terminal.
When a script has an error, it will receive SIGERR and we can trap it to send alarm to CloudWatch.
- Sending message to CloudWatch
We can send message to CloudWatch by aws cli put-log-events
command.
aws logs put-log-events
--log-group-name logGroupName
--log-stream-name logStreamName
--log-events timestamp=$timeStamp,message="message"
--sequence-token $UploadSequenceToken
Before we do this, we have to set a role to ec2 and this role has the put log permission.
Please refer to the AWS document for more details.
How to do it
main.sh
#!/bin/basherr_report() {
./cwlog.sh "Error at line $1"
}trap 'err_report $LINENO' ERR# for example
echo foo | grep bar # This is line number 10
cwlog.sh
#!/bin/bashEC2_AVAIL_ZONE=`curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone`
EC2_REGION="`echo \"$EC2_AVAIL_ZONE\" | sed 's/[a-z]$//'`"export AWS_DEFAULT_REGION=$EC2_REGIONMess="${1:-'Execute Error!'}"
LogGroupName="SystemOperations"
LogStreamName="test"UploadSequenceToken=$(aws logs describe-log-streams --log-group-name "$LogGroupName" --query 'logStreams[?logStreamName==`'$LogStreamName'`].[uploadSequenceToken]' --output text)echo $UploadSequenceTokenTimeStamp=`date "+%s%N" --utc`
TimeStamp=`expr $TimeStamp / 1000000`if [ "$UploadSequenceToken" != "None" ]
then
aws logs put-log-events --log-group-name "$LogGroupName" --log-stream-name "$LogStreamName" --log-events timestamp=$TimeStamp,message="$Mess" --sequence-token $UploadSequenceToken
else
# An upload in a newly created log stream does not require a sequence token.
aws logs put-log-events --log-group-name "$LogGroupName" --log-stream-name "$LogStreamName" --log-events timestamp=$TimeStamp,message="$Mess"
fi
Run main.sh and the message Error at line 10
will send to CloudWatch.