Skip to content

Instantly share code, notes, and snippets.

@dopiaza
Created September 5, 2013 12:33
Show Gist options
  • Save dopiaza/6449505 to your computer and use it in GitHub Desktop.
Save dopiaza/6449505 to your computer and use it in GitHub Desktop.
Post a message to a Slack channel
#!/bin/bash
# Usage: slackpost <token> <channel> <message>
# Enter the name of your slack host here - the thing that appears in your URL:
# https://slackhost.slack.com/
slackhost=PUT_YOUR_HOST_HERE
token=$1
if [[ $token == "" ]]
then
echo "No token specified"
exit 1
fi
shift
channel=$1
if [[ $channel == "" ]]
then
echo "No channel specified"
exit 1
fi
shift
text=$*
if [[ $text == "" ]]
then
echo "No text specified"
exit 1
fi
escapedText=$(echo $text | sed 's/"/\"/g' | sed "s/'/\'/g" )
json="{\"channel\": \"#$channel\", \"text\": \"$escapedText\"}"
curl -s -d "payload=$json" "https://$slackhost.slack.com/services/hooks/incoming-webhook?token=$token"
@stuinzuri
Copy link

Most excellent. Thanks.

@xecgr
Copy link

xecgr commented Jul 24, 2015

It seems that now the incoming-webhook behaviour is diferrent (with an unique url and without token). I've tried with a modificated version of your script, and it works like a charm:

#!/bin/bash

# Usage: slackpost "<webhook_url>" "<channel>" "<message>"

webhook_url=$1
if [[ $webhook_url == "" ]]
then
        echo "No webhook_url specified"
        exit 1
fi

shift
channel=$1
if [[ $channel == "" ]]
then
        echo "No channel specified"
        exit 1
fi

shift

text=$*

if [[ $text == "" ]]
then
        echo "No text specified"
        exit 1
fi

escapedText=$(echo $text | sed 's/"/\"/g' | sed "s/'/\'/g" )
json="{\"channel\": \"$channel\", \"text\": \"$escapedText\"}"

curl -s -d "payload=$json" "$webhook_url"

@hoahm
Copy link

hoahm commented Nov 21, 2015

I think it would be better if we have username, and some formatting

#!/bin/bash

# Usage: slackpost "<webhook_url>" "<channel>" "<username>" "<message>"

# ------------
webhook_url=$1
if [[ $webhook_url == "" ]]
then
        echo "No webhook_url specified"
        exit 1
fi

# ------------
shift
channel=$1
if [[ $channel == "" ]]
then
        echo "No channel specified"
        exit 1
fi

# ------------
shift
username=$1
if [[ $username == "" ]]
then
        echo "No username specified"
        exit 1
fi

# ------------
shift

text=$*

if [[ $text == "" ]]
then
        echo "No text specified"
        exit 1
fi

escapedText=$(echo $text | sed 's/"/\"/g' | sed "s/'/\'/g" )

json="{\"channel\": \"$channel\", \"username\":\"$username\", \"icon_emoji\":\"ghost\", \"attachments\":[{\"color\":\"danger\" , \"text\": \"$escapedText\"}]}"

curl -s -d "payload=$json" "$webhook_url"

@daviddarke
Copy link

LOVE

@bjbishop
Copy link

Yes, this is handy, thanks for sharing! What is the license on this @dopiaza?

@zkent
Copy link

zkent commented May 30, 2017

Does something need to be set up on the Slack side for this to work?

@gdoug-guidance
Copy link

gdoug-guidance commented Jun 2, 2017

@zkent You need to add an incoming webhook to your account.
https://api.slack.com/incoming-webhooks
https://my.slack.com/services/new/incoming-webhook/ (You will need to be logged in)

With the custom webhook url that is provided... you can use one of these fine scripts. ;)

@andkirby
Copy link

I made some my one. :)
https://gist.github.com/andkirby/67a774513215d7ba06384186dd441d9e
It allows to use ENV vars for channels/webhookURL.
Also it can push a message to several channels.

@firecentaur
Copy link

I get an error illegal option pipe fail

@vineethvijay
Copy link

This is pure awesome <3

@xavier-re
Copy link

adding capability to read multiple lines from stdin / pipe

#!/bin/bash

# Usage: slackpost "<webhook_url>" "<channel>" "<username>" "<message>"
# also (echo $RANDOM; echo $RANDOM) |slackpost "<channel>" "<username>"

# ------------
webhook_url=$1
if [[ $webhook_url == "" ]]
then
        echo "No webhook_url specified"
        exit 1
fi

# ------------
shift
channel=$1
if [[ $channel == "" ]]
then
        echo "No channel specified"
        exit 1
fi

# ------------
shift
username=$1
if [[ $username == "" ]]
then
        echo "No username specified"
        exit 1
fi

# ------------
shift

text=$*

if [[ $text == "" ]]
then
while IFS= read -r line; do
  #printf '%s\n' "$line"
  text="$text$line\n"
done
fi


if [[ $text == "" ]]
then
        echo "No text specified"
        exit 1
fi

escapedText=$(echo $text | sed 's/"/\"/g' | sed "s/'/\'/g" )

json="{\"channel\": \"$channel\", \"username\":\"$username\", \"icon_emoji\":\"ghost\", \"attachments\":[{\"color\":\"danger\" , \"text\": \"$escapedText\"}]}"

curl -s -d "payload=$json" "$webhook_url"

@lpaulmp
Copy link

lpaulmp commented Oct 18, 2017

bash in not the default in a couple of distros

#!/usr/bin/env bash

# Usage: slackpost "<webhook_url>" "<channel>" "<username>" "<message>"
# also (echo $RANDOM; echo $RANDOM) |slackpost "<channel>" "<username>"

# ------------
webhook_url=$1
if [[ $webhook_url == "" ]]
then
        echo "No webhook_url specified"
        exit 1
fi

# ------------
shift
channel=$1
if [[ $channel == "" ]]
then
        echo "No channel specified"
        exit 1
fi

# ------------
shift
username=$1
if [[ $username == "" ]]
then
        echo "No username specified"
        exit 1
fi

# ------------
shift

text=$*

if [[ $text == "" ]]
then
while IFS= read -r line; do
  #printf '%s\n' "$line"
  text="$text$line\n"
done
fi


if [[ $text == "" ]]
then
        echo "No text specified"
        exit 1
fi

escapedText=$(echo $text | sed 's/"/\"/g' | sed "s/'/\'/g" )

json="{\"channel\": \"$channel\", \"username\":\"$username\", \"icon_emoji\":\"ghost\", \"attachments\":[{\"color\":\"danger\" , \"text\": \"$escapedText\"}]}"

curl -s -d "payload=$json" "$webhook_url"

@a-sync
Copy link

a-sync commented Nov 28, 2017

Thank you all for the updates!
I was happy to use this as a fast and short solution, but found that it had multiple shortcomings, and the mandatory options made it painful to write a quick one liner to pipe all my output to slack.

If anyone is interested, i created a new version starting from the updates uploaded here, although it ended up as a complete rewrite with a much simpler API, proper JSON escaping and STDIN handling and optional configs to overwrite the default channel, bot name, etc.
Available here: http://github.com/a-sync/slackr

Another good alternative i found: https://github.com/course-hero/slacktee

Copy link

ghost commented Mar 3, 2018

Can anybody tell how to send message to the specific user?
bash slackpost webhook channel message - works
bash slackpost webhook @user message - Doesn't work. It says "channel_not_found"

Copy link

ghost commented Mar 18, 2018

Ask Linux system to send the traditional Chinese message to slack, and it will change to the code! How do you deal with it? Thx

@silenced1
Copy link

silenced1 commented Jul 23, 2018

@PetroPliuta - You may have found the answer to your question, but when targeting a user, you have to use their id instead of their name.
Example: "<@U3BV0GGY3>" or "U3BV0GGY3" depending on the API usage

In Slack: Click the user, then click their name and go to "View 's profile", then click the Down Arrow next to "Message" and you'll see "Copy member id".

You can also see this if you visit the following link (while you're logged into slack), click your name next to the "user" field and click "Test Method". This will show you a bunch of information about the user.
https://api.slack.com/methods/users.info/test

@miguelmota
Copy link

miguelmota commented May 12, 2019

Here's a version which uses argument flags:

#!/usr/bin/env bash

# Usage: slackpost -w <webhook_url> -c <channel> -u <username> -m <message> [-a <alert_type>]
# Usage: echo <message> | slackpost -w <webhook_url> -c <channel> -u <username> [-a <alert_type>]

# exit immediately if a command exits with a non-zero status
set -e

# error if variable referenced before being set
set -u

# produce failure return code if any command fails in pipe
set -o pipefail

# accepted values: good, warning, danger
alert_type=""
channel=""
message=""
username=""
webhook_url=""

# colon after var means it has a value rather than it being a bool flag
while getopts 'a:c:m:u:w:' OPTION; do
  case "$OPTION" in
    a)
      alert_type="$OPTARG"
      ;;
    c)
      channel="$OPTARG"
      ;;
    m)
      message="$OPTARG"
      ;;
    u)
      username="$OPTARG"
      ;;
    w)
      webhook_url="$OPTARG"
      ;;
    ?)
      echo "script usage: $(basename $0) {-c channel} {-m message} {-u username} {-w webhook} [-a alert_type]" >&2
      exit 1
      ;;
  esac
done
shift "$(($OPTIND -1))"

# exit if channel not provided
if [[ -z "$channel" ]]
then
  echo "No channel specified"
  exit 1
fi

# read piped data as message if message argument is not provided
if [[ -z "$message" ]]
then
  message=$*

  while IFS= read -r line; do
    message="$message$line\n"
  done
fi

# exit if username not provided
if [[ -z "$username" ]]
then
  echo "No username specified"
  exit 1
fi

# exit if webhook not provided
if [[ -z "$webhook_url" ]]
then
  echo "No webhook_url specified"
  exit 1
fi

# escape message text
escapedText=$(echo $message | sed 's/"/\"/g' | sed "s/'/\'/g")

# create JSON payload
json="{\"channel\": \"$channel\", \"username\":\"$username\", \"icon_emoji\":\"ghost\", \"attachments\":[{\"color\":\"$alert_type\" , \"text\": \"$escapedText\"}]}"

# fire off slack message post
curl -s -d "payload=$json" "$webhook_url"

@hari-mopuri
Copy link

Can you explain for posting slash command using api ?

Copy link

ghost commented May 31, 2019

I should upload my version, it's updated to use the API better ...

@romaopedro
Copy link

romaopedro commented Sep 25, 2019

Don't add the payload key before json variable.
And add the token in the headers.

curl -v \
	-H 'Content-Type:application/json; charset=utf-8' \
	-H 'Authorization: Bearer xoxp-XXXXXX-XXXX-XXXXXXXX \
	--data "$json" \
	"$slackwebhook"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment