├── .gitignore ├── examples ├── histo-server-random-data.sh ├── wall-server.sh ├── histo-server.sh └── cpu-stream.sh ├── package.json ├── test ├── push.sh └── recv.sh ├── help.sh ├── test.sh ├── umq-push.1.md ├── umq-recv.1.md ├── umq-push.1 ├── umq-recv.1 ├── Makefile ├── umq.sh ├── push.sh ├── umq.1.md ├── README.md ├── umq.1 └── recv.sh /.gitignore: -------------------------------------------------------------------------------- 1 | umq 2 | umq-push 3 | umq-recv 4 | umq-help 5 | -------------------------------------------------------------------------------- /examples/histo-server-random-data.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | while true; do 4 | echo $RANDOM 5 | sleep .5 6 | done | umq push localhost 3000 7 | -------------------------------------------------------------------------------- /examples/wall-server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | umq recv "$1" "$2" | { 4 | while read -r chunk; do 5 | echo "$chunk" | wall 6 | done 7 | } 8 | -------------------------------------------------------------------------------- /examples/histo-server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | umq recv "$1" "$2" | { 4 | # init view 5 | echo 0 6 | while read -r chunk; do 7 | echo "$chunk" 8 | done 9 | exit 0 10 | } | histo; 11 | 12 | exit $?; 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "umq", 3 | "version": "0.0.1", 4 | "description": "tcp message pushing and receiving in bash", 5 | "scripts": [ "umq.sh", "recv.sh", "push.sh", "help.sh" ], 6 | "install": "make install" 7 | } 8 | -------------------------------------------------------------------------------- /test/push.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "$EXPECTED" | $UMQ_PUSH "$HOST" "$PORT" 4 | 5 | if [ "0" != "$?" ]; then 6 | echo "recv: umq connect error" 7 | exit $? 8 | fi 9 | 10 | if [ "0" = "$?" ]; then 11 | echo "push: ok" 12 | else 13 | echo "push: fail" 14 | fi 15 | -------------------------------------------------------------------------------- /help.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | CMD="$1" 4 | CMD_PATH="`which umq-$CMD`" 5 | 6 | if [ "umq" = "$CMD" ]; then 7 | man umq 8 | exit 0 9 | elif [ -z "$CMD_PATH" ]; then 10 | { 11 | echo "unknown command '$CMD'"; 12 | } >&2 13 | exit 1 14 | else 15 | man "umq-$CMD" 16 | exit 0 17 | fi 18 | -------------------------------------------------------------------------------- /test/recv.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # server 4 | $UMQ_RECV "$PORT" -s | { 5 | while read -r line; do 6 | if [ "" = "$line" ]; then 7 | continue 8 | fi 9 | 10 | echo "got: $line" 11 | echo "expected: $EXPECTED" 12 | 13 | if [ "$line" != "$EXPECTED" ]; then 14 | throw "'$line' != '$EXPECTED'" 15 | fi 16 | 17 | break 18 | done; 19 | 20 | if [ "0" = "$?" ]; then 21 | echo "recv: ok" 22 | else 23 | echo "recv: fail" 24 | fi 25 | } 26 | 27 | if [ "0" != "$?" ]; then 28 | echo "recv: umq bind error" 29 | exit $? 30 | fi 31 | -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export OS="`uname`" 4 | export UMQ="`pwd`/umq" 5 | export UMQ_PUSH="$UMQ-push" 6 | export UMQ_RECV="$UMQ-recv" 7 | 8 | export EXPECTED="beep" 9 | export HOST="localhost" 10 | export PORT=3000 11 | 12 | throw () { 13 | { 14 | printf "error: " 15 | printf "%s" "$@" 16 | printf "\n" 17 | } >&2 18 | 19 | exit 1; 20 | } 21 | 22 | if [ "Darwin" = "$OS" ]; then 23 | export -f throw 24 | else 25 | export throw 26 | fi 27 | 28 | 29 | echo "starting receiver" 30 | ./test/recv.sh & 31 | test_recv_pid=$! 32 | 33 | sleep .5 34 | echo "pushing '$EXPECTED'.." 35 | ./test/push.sh 36 | test_push_pid=$! 37 | 38 | echo "ok" 39 | -------------------------------------------------------------------------------- /umq-push.1.md: -------------------------------------------------------------------------------- 1 | umq-push(1) -- tcp/udp push message transport utility 2 | ================================= 3 | 4 | ## SYNOPSIS 5 | 6 | `umq-push ` [-hvV] 7 | 8 | ## OPTIONS 9 | 10 | `-v, --verbose` show verbose output 11 | `-h, --help` display this message 12 | `-V, --version` output version 13 | 14 | ## USAGE 15 | 16 | ``` 17 | $ echo "ping" | umq push localhost 3000 18 | ``` 19 | 20 | ## AUTHOR 21 | 22 | - Joseph Werle 23 | 24 | ## REPORTING BUGS 25 | 26 | - https://github.com/jwerle/umq/issues 27 | 28 | ## SEE ALSO 29 | 30 | - https://github.com/jwerle/umq 31 | 32 | ## LICENSE 33 | 34 | MIT (C) Copyright Joseph Werle 2013 35 | -------------------------------------------------------------------------------- /umq-recv.1.md: -------------------------------------------------------------------------------- 1 | umq-recv(1) -- tcp/udp listen transport utility 2 | ================================= 3 | 4 | ## SYNOPSIS 5 | 6 | `umq-recv ` [-hsvV] [-f ] 7 | 8 | ## OPTIONS 9 | 10 | `-f, --file` file to execute on each chunk received 11 | `-s, --single` close after first connection 12 | `-v, --verbose` show verbose output 13 | `-h, --help` display this message 14 | `-V, --version` output version 15 | 16 | ## USAGE 17 | 18 | ``` 19 | $ umq push localhost 3000 20 | ``` 21 | 22 | ## AUTHOR 23 | 24 | - Joseph Werle 25 | 26 | ## REPORTING BUGS 27 | 28 | - https://github.com/jwerle/umq/issues 29 | 30 | ## SEE ALSO 31 | 32 | - https://github.com/jwerle/umq 33 | 34 | ## LICENSE 35 | 36 | MIT (C) Copyright Joseph Werle 2013 37 | -------------------------------------------------------------------------------- /umq-push.1: -------------------------------------------------------------------------------- 1 | .\" Generated with Ronnjs 0.3.8 2 | .\" http://github.com/kapouer/ronnjs/ 3 | . 4 | .TH "UMQ\-PUSH" "1" "December 2013" "" "" 5 | . 6 | .SH "NAME" 7 | \fBumq-push\fR \-\- tcp/udp push message transport utility 8 | . 9 | .SH "SYNOPSIS" 10 | \fBumq\-push \fR [\-hvV] 11 | . 12 | .SH "OPTIONS" 13 | \fB\-v, \-\-verbose\fR show verbose output 14 | \fB\-h, \-\-help\fR display this message 15 | \fB\-V, \-\-version\fR output version 16 | . 17 | .SH "USAGE" 18 | \fB 19 | $ echo "ping" | umq push localhost 3000\fR 20 | . 21 | .SH "AUTHOR" 22 | . 23 | .IP "\(bu" 4 24 | Joseph Werle \fIjoseph\.werle@gmail\.com\fR 25 | . 26 | .IP "" 0 27 | . 28 | .SH "REPORTING BUGS" 29 | . 30 | .IP "\(bu" 4 31 | https://github\.com/jwerle/umq/issues 32 | . 33 | .IP "" 0 34 | . 35 | .SH "SEE ALSO" 36 | . 37 | .IP "\(bu" 4 38 | https://github\.com/jwerle/umq 39 | . 40 | .IP "" 0 41 | . 42 | .SH "LICENSE" 43 | MIT (C) Copyright Joseph Werle 2013 -------------------------------------------------------------------------------- /umq-recv.1: -------------------------------------------------------------------------------- 1 | .\" Generated with Ronnjs 0.3.8 2 | .\" http://github.com/kapouer/ronnjs/ 3 | . 4 | .TH "UMQ\-RECV" "1" "December 2013" "" "" 5 | . 6 | .SH "NAME" 7 | \fBumq-recv\fR \-\- tcp/udp listen transport utility 8 | . 9 | .SH "SYNOPSIS" 10 | \fBumq\-recv \fR [\-hsvV] [\-f ] 11 | . 12 | .SH "OPTIONS" 13 | \fB\-f, \-\-file\fR file to execute on each chunk received 14 | \fB\-s, \-\-single\fR close after first connection 15 | \fB\-v, \-\-verbose\fR show verbose output 16 | \fB\-h, \-\-help\fR display this message 17 | \fB\-V, \-\-version\fR output version 18 | . 19 | .SH "USAGE" 20 | \fB 21 | $ umq push localhost 3000\fR 22 | . 23 | .SH "AUTHOR" 24 | . 25 | .IP "\(bu" 4 26 | Joseph Werle \fIjoseph\.werle@gmail\.com\fR 27 | . 28 | .IP "" 0 29 | . 30 | .SH "REPORTING BUGS" 31 | . 32 | .IP "\(bu" 4 33 | https://github\.com/jwerle/umq/issues 34 | . 35 | .IP "" 0 36 | . 37 | .SH "SEE ALSO" 38 | . 39 | .IP "\(bu" 4 40 | https://github\.com/jwerle/umq 41 | . 42 | .IP "" 0 43 | . 44 | .SH "LICENSE" 45 | MIT (C) Copyright Joseph Werle 2013 -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | BIN = umq 3 | BINS = push recv help 4 | EXAMPLES = wall-server histo-server 5 | PREFIX ?= /usr/local 6 | MANPREFIX ?= $(PREFIX)/share/man/man1 7 | 8 | $(BIN): clean $(BINS) 9 | ln -s $(BIN).sh $(BIN) 10 | 11 | $(BINS): 12 | ln -s $@.sh umq-$@ 13 | 14 | install: $(BIN) 15 | @echo " +bin" 16 | @install $(BIN) $(PREFIX)/bin 17 | $(foreach bin,$(BINS),$(shell install umq-$(bin) $(PREFIX)/bin/umq-$(bin))) 18 | @echo " +doc" 19 | @install $(BIN).1 $(MANPREFIX) 20 | $(foreach bin,$(BINS),$(shell install umq-$(bin).1 $(MANPREFIX))) 21 | 22 | uninstall: clean 23 | @echo " -bin" 24 | @rm -f $(PREFIX)/bin/$(BIN) 25 | $(foreach bin,$(BINS),$(shell rm -f $(PREFIX)/bin/umq-$(bin))) 26 | @echo " -doc" 27 | $(foreach bin,$(BINS),$(shell rm -f $(MAXPREFIX)/umq-$(bin).1)) 28 | @echo " -examples" 29 | $(foreach bin,$(BINS),$(shell rm -f $(PREFIX)/bin/$(bin))) 30 | 31 | examples: $(EXAMPLES) 32 | 33 | $(EXAMPLES): 34 | install examples/$@.sh $(PREFIX)/bin/$@ 35 | 36 | cpu-stream: 37 | @./umq-recv 9999 -f ./examples/cpu-stream.sh -v 38 | 39 | clean: 40 | rm -f $(BIN) 41 | $(foreach bin,$(BINS),$(shell rm -f umq-$(bin))) 42 | 43 | check: test 44 | test: 45 | ./test.sh 46 | 47 | doc: 48 | @echo "$(BIN).1"; 49 | @curl -# -F page=@$(BIN).1.md -o $(BIN).1 http://mantastic.herokuapp.com 50 | @for bin in $(BINS); do \ 51 | if ! test -f "umq-$$bin.1"; then continue; fi; \ 52 | echo "umq-$$bin.1"; \ 53 | curl -# -F page=@"umq-$$bin.1.md" -o "umq-$$bin.1" http://mantastic.herokuapp.com; \ 54 | done; 55 | 56 | .PHONY: test 57 | -------------------------------------------------------------------------------- /umq.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SELF="$0" 4 | VERSION="0.0.1" 5 | NULL=/dev/null 6 | STDIN=0 7 | STDOUT=1 8 | STDERR=2 9 | 10 | if [ -t 0 ]; then 11 | ISATTY=1 12 | else 13 | ISATTY=0 14 | fi 15 | 16 | version () { 17 | echo $VERSION 18 | } 19 | 20 | usage () { 21 | echo "usage: umq [-hV]" 22 | 23 | if [ "$1" = "1" ]; then 24 | echo 25 | echo "examples:" 26 | echo "$ echo \"hello world\" | umq push localhost 3000" 27 | echo "$ umq recv localhost 3000 | while read line; do \\ 28 | echo \"msg: \$line\"; done" 29 | echo 30 | echo "commands:" 31 | echo " push push message to host with port" 32 | echo " recv receive message on host with port" 33 | echo " help see more information on a command" 34 | echo 35 | echo "options:" 36 | echo " -h, --help display this message" 37 | echo " -V, --version output version" 38 | fi 39 | } 40 | 41 | 42 | while true; do 43 | arg="$1" 44 | 45 | if [ "" = "$1" ]; then 46 | break; 47 | fi 48 | 49 | if [ "${arg:0:1}" != "-" ]; then 50 | cmd="$1" 51 | cmd_path="`which umq-${cmd}`" 52 | has_cmd=$? 53 | shift 54 | break; 55 | fi 56 | 57 | case $arg in 58 | -h|--help) 59 | usage 1 60 | exit 1 61 | ;; 62 | 63 | -V|--version) 64 | version 65 | exit 0 66 | ;; 67 | 68 | *) 69 | { 70 | echo "unknown option \`$arg'" 71 | usage 72 | } >&$STDERR 73 | exit 1 74 | ;; 75 | esac 76 | done 77 | 78 | if [ ! -z "$cmd" ] && [ "0" = "$has_cmd" ]; then 79 | $cmd_path $@ 80 | elif [ ! -z "$cmd" ]; then 81 | { 82 | echo "unknown command '$cmd'" 83 | usage 84 | } >&$STDERR 85 | exit 1 86 | else 87 | usage 1 88 | exit 1 89 | fi 90 | -------------------------------------------------------------------------------- /examples/cpu-stream.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # ps -eo pcpu,pid,user,args | sort -r -k1 4 | 5 | PS="ps" 6 | VERSION="0.0.1" 7 | 8 | version () { 9 | echo $VERSION 10 | } 11 | 12 | usage () { 13 | echo "usage: cpu-stream [-hvV] [-u ] [-f ]" 14 | echo " [-c ] [-p ]" 15 | 16 | if [ "$1" = "1" ]; then 17 | echo 18 | echo "options:" 19 | echo " -p, --port port to emit on (default: 3000)" 20 | echo " -u, --user filter on user" 21 | echo " -f, --filter grep pattern syntax to filter" 22 | echo " -c, --column a csv of columns for \`ps' (default: pcpu)" 23 | echo " -v, --verbose show verbose output" 24 | echo " -h, --help display this message" 25 | echo " -V, --version output version" 26 | fi 27 | } 28 | 29 | column="pcpu" 30 | port="3000" 31 | user="" 32 | filter="" 33 | 34 | while true; do 35 | arg="$1" 36 | 37 | if [ "" = "$1" ]; then 38 | break; 39 | fi 40 | 41 | if [ "${arg:0:1}" != "-" ]; then 42 | shift 43 | break; 44 | fi 45 | 46 | case $arg in 47 | -p|--port) 48 | port="$2" 49 | shift 2 50 | ;; 51 | 52 | -u|--user) 53 | user="$2" 54 | column="${column},user" 55 | shift 2 56 | ;; 57 | 58 | -f|--filter) 59 | filter="$2" 60 | shift 2 61 | ;; 62 | 63 | -c|--column) 64 | column="$2" 65 | shift 2 66 | ;; 67 | 68 | -h|--help) 69 | usage 1 70 | exit 1 71 | ;; 72 | 73 | -V|--version) 74 | version 75 | exit 0 76 | ;; 77 | 78 | -v|--verbose) 79 | VERBOSE="--verbose" 80 | shift 81 | ;; 82 | 83 | *) 84 | { 85 | echo "unknown option \`$arg'" 86 | usage 87 | } >&$STDERR 88 | exit 1 89 | ;; 90 | esac 91 | done 92 | 93 | "${PS}" -eo "${column}" | sort -r -k2 | tail -n +2 | grep "${user}" | grep "${filter}" | head -1 | { 94 | while read -r n; do 95 | case "$n" in 96 | **[0-9]**) 97 | v="`echo \"$n * 100\" | bc`" 98 | printf "%1.f\n" "$v" 99 | sleep .5 100 | ;; 101 | esac 102 | done 103 | }; 104 | 105 | exit $? 106 | -------------------------------------------------------------------------------- /push.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SELF="$0" 4 | VERSION="0.0.1" 5 | NULL=/dev/null 6 | STDIN=0 7 | STDOUT=1 8 | STDERR=2 9 | VERBOSE=0 10 | 11 | if [ -t 0 ]; then 12 | ISATTY=1 13 | else 14 | ISATTY=0 15 | fi 16 | 17 | throw () { 18 | { 19 | printf "push: error: " 20 | echo "$@" 21 | } >&$STDERR 22 | 23 | exit 1 24 | } 25 | 26 | version () { 27 | echo $VERSION 28 | } 29 | 30 | verbose () { 31 | if [ "1" = "$VERBOSE" ]; then 32 | printf "push: verbose: " 33 | printf "$@" 34 | printf "\n" 35 | fi 36 | } 37 | 38 | usage () { 39 | echo "usage: umq push [-hvV] " 40 | 41 | if [ "$1" = "1" ]; then 42 | echo 43 | echo "examples:" 44 | echo "$ echo \"ping\" | umq push localhost 3000" 45 | echo 46 | echo "options:" 47 | echo " -v, --verbose show verbose output" 48 | echo " -h, --help display this message" 49 | echo " -V, --version output version" 50 | fi 51 | } 52 | 53 | if [ "${1:0:1}" != "-" ]; then 54 | host="$1" 55 | shift 56 | fi 57 | 58 | if [ "${1:0:1}" != "-" ]; then 59 | port="$1" 60 | shift 61 | fi 62 | 63 | while true; do 64 | arg="$1" 65 | 66 | if [ "" = "$1" ]; then 67 | break; 68 | fi 69 | 70 | if [ "${arg:0:1}" != "-" ]; then 71 | shift 72 | continue 73 | fi 74 | 75 | case $arg in 76 | -v|--verbose) 77 | VERBOSE=1 78 | shift 79 | ;; 80 | 81 | -h|--help) 82 | usage 1 83 | exit 1 84 | ;; 85 | 86 | -V|--version) 87 | version 88 | exit 0 89 | ;; 90 | 91 | *) 92 | { 93 | echo "unknown option \`$arg'" 94 | } >&$STDERR 95 | usage 96 | exit 1 97 | ;; 98 | esac 99 | done 100 | 101 | verbose "host='%s'" "$host" 102 | verbose "port='%s'" "$port" 103 | 104 | if [ -z "$host" ]; then 105 | throw "Missing host" 106 | elif [ -z "$port" ]; then 107 | throw "Missing port" 108 | fi 109 | 110 | while read -r line; do 111 | verbose "push: '%s'" "$line" 112 | echo "$line" | { 113 | nc "$host" "$port" | { 114 | while read chunk; do 115 | if [ "" != "$chunk" ]; then 116 | echo "$chunk" 117 | fi 118 | done 119 | } >$NULL 120 | 121 | if [ "1" = "$?" ]; then 122 | throw "Failed to connect to '$host:$port'" 123 | fi 124 | }; 125 | done 126 | -------------------------------------------------------------------------------- /umq.1.md: -------------------------------------------------------------------------------- 1 | umq(1) -- tcp message transport utility 2 | ================================= 3 | 4 | ## SYNOPSIS 5 | 6 | `umq` [-hV] 7 | 8 | ## OPTIONS 9 | 10 | `-h, --help` display this message 11 | `-V, --version` output version 12 | 13 | ## COMMANDS 14 | 15 | Push a message to a host with port 16 | 17 | `$ umq push ` 18 | 19 | Receive a message on a host with port 20 | 21 | `$ umq recv ` 22 | 23 | Display help on a command 24 | 25 | `$ umq help push` 26 | 27 | ## EXAMPLES 28 | 29 | `$ echo "hello world" | umq push localhost 3000` 30 | 31 | ``` 32 | $ umq recv localhost 3000 | { \ 33 | while read line; do \ 34 | echo "msg: $line"; \ 35 | done; \ 36 | } 37 | ``` 38 | 39 | ## USAGE 40 | 41 | ### SERVER 42 | 43 | Listening on localhost can be achieved by simple providing a port: 44 | 45 | ``` 46 | $ umq recv 3000 | { \ 47 | while read -r line; do \ 48 | echo "got: '$line'"; \ 49 | done; \ 50 | } 51 | ``` 52 | 53 | This will create a server and listen on localhost port `3000` for all 54 | incoming tcp messages. 55 | 56 | ### CONNECTING 57 | 58 | You can connect and read from the server by using `umq recv` with a host 59 | and port: 60 | 61 | `$ umq recv localhost 3000` 62 | 63 | ### PUSHING 64 | 65 | Pushing data to a umq receiver can be performed via `umq push`: 66 | 67 | `$ echo "ping" | umq push localhost 3000` 68 | 69 | This should yield the following response on the server: 70 | 71 | `got: 'ping'` 72 | 73 | ## CAVEATS 74 | 75 | When multiple peers are connected via `umq recv ` to a single 76 | umq receiver, messages are emitted to each peer via the RR (Round-Robin) 77 | 78 | ### SERVER 79 | 80 | ``` 81 | $ umq recv 3000 | while read -r chunk; do echo "chunk: $chunk"; done 82 | chunk: 83 | chunk: 0 84 | chunk: 1 85 | chunk: 2 86 | chunk: 3 87 | chunk: 4 88 | chunk: 5 89 | chunk: 6 90 | chunk: 7 91 | chunk: 8 92 | chunk: 9 93 | chunk: 10 94 | chunk: 11 95 | ``` 96 | 97 | ### PUSHER 98 | 99 | ``` 100 | $ i=0 while true; do echo echo "$i"; ((++i)); sleep .5; done | \ 101 | umq push localhost 3000 102 | ``` 103 | 104 | ### PEER 1 105 | ``` 106 | $ umq recv localhost 3000 107 | 108 | 2 109 | 3 110 | 4 111 | 5 112 | 8 113 | 9 114 | 10 115 | 11 116 | ``` 117 | 118 | ### PEER 2 119 | 120 | ``` 121 | $ umq recv localhost 3000 122 | 123 | 6 124 | 7 125 | ``` 126 | 127 | ## AUTHOR 128 | 129 | - Joseph Werle 130 | 131 | ## REPORTING BUGS 132 | 133 | - https://github.com/jwerle/umq/issues 134 | 135 | ## SEE ALSO 136 | 137 | - https://github.com/jwerle/umq 138 | 139 | ## LICENSE 140 | 141 | MIT (C) Copyright Joseph Werle 2013 142 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | umq 2 | ===== 3 | 4 | tcp message pushing and receiving in bash 5 | 6 | ## install 7 | 8 | [bpkg](https://github.com/bpkg/bpkg) 9 | 10 | ```sh 11 | $ bpkg install umq -g 12 | ``` 13 | 14 | ```sh 15 | $ make 16 | $ make check 17 | $ make install 18 | ``` 19 | 20 | ## usage 21 | 22 | **server** 23 | 24 | Listening on localhost can be achieved by simple providing a port: 25 | 26 | ```sh 27 | $ umq recv 3000 | { \ 28 | while read -r line; do \ 29 | echo "got: '$line'"; \ 30 | done; \ 31 | } 32 | ``` 33 | 34 | This will create a server and listen on localhost port `3000` for all incoming tcp messages. 35 | 36 | **connecting** 37 | 38 | You can connect and read from the server by using `umq recv` with a host and port: 39 | 40 | ```sh 41 | $ umq recv localhost 3000 42 | ``` 43 | 44 | **pushing** 45 | 46 | Pushing data to a umq receiver can be performed via `umq push`: 47 | 48 | ```sh 49 | $ echo "ping" | umq push localhost 3000 50 | ``` 51 | 52 | This should yield the following response on the server: 53 | 54 | ``` 55 | got: 'ping' 56 | ``` 57 | 58 | ## api 59 | 60 | ```sh 61 | usage: umq [-hV] 62 | 63 | examples: 64 | $ echo "hello world" | umq push localhost 3000 65 | $ umq recv localhost 3000 | while read line; do \ 66 | echo "msg: $line"; done 67 | 68 | commands: 69 | push push message to host with port 70 | recv receive message on host with port 71 | help see more information on a command 72 | 73 | options: 74 | -h, --help display this message 75 | -V, --version output version 76 | ``` 77 | 78 | ## examples 79 | 80 | ### cpu histogram 81 | 82 | Using `umq` with [histo](https://github.com/visionmedia/histo) allows 83 | for data to be streamed via tcp to a histo chart 84 | 85 | See [cpu-stream](https://gist.github.com/jwerle/8076956) for a preview. 86 | 87 | ### wall server 88 | 89 | Streaming messages to `wall`. 90 | 91 | See [wall-server](https://github.com/jwerle/umq/blob/master/examples/wall-server.sh). 92 | 93 | ## caveats 94 | 95 | When multiple peers are connected via `umq recv ` to a single umq receiver, messages are emitted to 96 | each peer via the (RR) [Round-Robin](http://en.wikipedia.org/wiki/Round-robin_scheduling) technique. For example: 97 | 98 | **server** 99 | 100 | ```sh 101 | $ umq recv 3000 | while read -r chunk; do echo "chunk: $chunk"; done 102 | chunk: 103 | chunk: 0 104 | chunk: 1 105 | chunk: 2 106 | chunk: 3 107 | chunk: 4 108 | chunk: 5 109 | chunk: 6 110 | chunk: 7 111 | chunk: 8 112 | chunk: 9 113 | chunk: 10 114 | chunk: 11 115 | ``` 116 | 117 | **pusher** 118 | 119 | ```sh 120 | $ i=0 while true; do echo echo "$i"; ((++i)); sleep .5; done | umq push localhost 3000 121 | ``` 122 | 123 | **peer 1** 124 | 125 | ```sh 126 | $ umq recv localhost 3000 127 | 128 | 2 129 | 3 130 | 4 131 | 5 132 | 8 133 | 9 134 | 10 135 | 11 136 | ``` 137 | 138 | **peer 2** 139 | 140 | ```sh 141 | $ umq recv localhost 3000 142 | 143 | 6 144 | 7 145 | ``` 146 | 147 | 148 | ## license 149 | 150 | MIT 151 | -------------------------------------------------------------------------------- /umq.1: -------------------------------------------------------------------------------- 1 | .\" Generated with Ronnjs 0.3.8 2 | .\" http://github.com/kapouer/ronnjs/ 3 | . 4 | .TH "UMQ" "1" "December 2013" "" "" 5 | . 6 | .SH "NAME" 7 | \fBumq\fR \-\- tcp message transport utility 8 | . 9 | .SH "SYNOPSIS" 10 | \fBumq\fR [\-hV] 11 | . 12 | .SH "OPTIONS" 13 | \fB\-h, \-\-help\fR display this message 14 | \fB\-V, \-\-version\fR output version 15 | . 16 | .SH "COMMANDS" 17 | Push a message to a host with port 18 | . 19 | .P 20 | \fB$ umq push \fR 21 | . 22 | .P 23 | Receive a message on a host with port 24 | . 25 | .P 26 | \fB$ umq recv \fR 27 | . 28 | .P 29 | Display help on a command 30 | . 31 | .P 32 | \fB$ umq help push\fR 33 | . 34 | .SH "EXAMPLES" 35 | \fB$ echo "hello world" | umq push localhost 3000\fR 36 | . 37 | .P 38 | \fB 39 | $ umq recv localhost 3000 | { \\ 40 | while read line; do \\ 41 | echo "msg: $line"; \\ 42 | done; \\ 43 | } 44 | \fR 45 | . 46 | .SH "USAGE" 47 | . 48 | .SS "SERVER" 49 | Listening on localhost can be achieved by simple providing a port: 50 | . 51 | .P 52 | \fB 53 | $ umq recv 3000 | { \\ 54 | while read \-r line; do \\ 55 | echo "got: \'$line\'"; \\ 56 | done; \\ 57 | } 58 | \fR 59 | . 60 | .P 61 | This will create a server and listen on localhost port \fB3000\fR for all 62 | incoming tcp messages\. 63 | . 64 | .SS "CONNECTING" 65 | You can connect and read from the server by using \fBumq recv\fR with a host 66 | and port: 67 | . 68 | .P 69 | \fB$ umq recv localhost 3000\fR 70 | . 71 | .SS "PUSHING" 72 | Pushing data to a umq receiver can be performed via \fBumq push\fR: 73 | . 74 | .P 75 | \fB$ echo "ping" | umq push localhost 3000\fR 76 | . 77 | .P 78 | This should yield the following response on the server: 79 | . 80 | .P 81 | \fBgot: \'ping\'\fR 82 | . 83 | .SH "CAVEATS" 84 | When multiple peers are connected via \fBumq recv \fR to a single 85 | umq receiver, messages are emitted to each peer via the RR (Round\-Robin) 86 | . 87 | .SS "SERVER" 88 | \fB 89 | $ umq recv 3000 | while read \-r chunk; do echo "chunk: $chunk"; done 90 | chunk: 91 | chunk: 0 92 | chunk: 1 93 | chunk: 2 94 | chunk: 3 95 | chunk: 4 96 | chunk: 5 97 | chunk: 6 98 | chunk: 7 99 | chunk: 8 100 | chunk: 9 101 | chunk: 10 102 | chunk: 11 103 | \fR 104 | . 105 | .SS "PUSHER" 106 | \fB 107 | $ i=0 while true; do echo echo "$i"; ((++i)); sleep \.5; done | \\ 108 | umq push localhost 3000 109 | \fR 110 | . 111 | .SS "PEER 1" 112 | \fB\fR` 113 | $ umq recv localhost 3000 114 | . 115 | .P 116 | 2 117 | 3 118 | 4 119 | 5 120 | 8 121 | 9 122 | 10 123 | 11 124 | \fB\fR` 125 | . 126 | .SS "PEER 2" 127 | \fB\fR` 128 | $ umq recv localhost 3000 129 | . 130 | .P 131 | 6 132 | 7 133 | \fB\fR` 134 | . 135 | .SH "AUTHOR" 136 | . 137 | .IP "\(bu" 4 138 | Joseph Werle \fIjoseph\.werle@gmail\.com\fR 139 | . 140 | .IP "" 0 141 | . 142 | .SH "REPORTING BUGS" 143 | . 144 | .IP "\(bu" 4 145 | https://github\.com/jwerle/umq/issues 146 | . 147 | .IP "" 0 148 | . 149 | .SH "SEE ALSO" 150 | . 151 | .IP "\(bu" 4 152 | https://github\.com/jwerle/umq 153 | . 154 | .IP "" 0 155 | . 156 | .SH "LICENSE" 157 | MIT (C) Copyright Joseph Werle 2013 -------------------------------------------------------------------------------- /recv.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SELF="$0" 4 | VERSION="0.0.1" 5 | NULL=/dev/null 6 | STDIN=0 7 | STDOUT=1 8 | STDERR=2 9 | 10 | if [ -z "$TMPDIR" ]; then 11 | TMPDIR="/tmp" 12 | fi 13 | 14 | if [ -t 0 ]; then 15 | ISATTY=1 16 | else 17 | ISATTY=0 18 | fi 19 | 20 | throw () { 21 | { 22 | printf "recv: error: " 23 | echo "$@" 24 | } >&$STDERR 25 | 26 | exit 1 27 | } 28 | 29 | verbose () { 30 | if [ "1" = "$VERBOSE" ]; then 31 | printf "recv: verbose: " 32 | printf "$@" 33 | printf "\n" 34 | fi 35 | } 36 | 37 | version () { 38 | echo $VERSION 39 | } 40 | 41 | usage () { 42 | echo "usage: umq recv [-hsvV] [-f ]" 43 | 44 | if [ "$1" = "1" ]; then 45 | echo 46 | echo "examples:" 47 | echo "$ umq recv localhost 3000 | { \\ 48 | while read -r ch; do echo \"\$ch\"; done" 49 | echo 50 | echo "options:" 51 | echo " -f, --file file to execute on each chunk received" 52 | echo " -s, --single close after first connection" 53 | echo " -v, --verbose show verbose output" 54 | echo " -h, --help display this message" 55 | echo " -V, --version output version" 56 | fi 57 | } 58 | 59 | if [ "${1:0:1}" != "-" ]; then 60 | host="$1" 61 | shift 62 | fi 63 | 64 | if [ "${1:0:1}" != "-" ]; then 65 | port="$1" 66 | shift 67 | else 68 | port="$host" 69 | fi 70 | 71 | if [ -z "$port" ]; then 72 | port="$host" 73 | fi 74 | 75 | if [ -z "$host" ]; then 76 | host="" 77 | fi 78 | 79 | while true; do 80 | arg="$1" 81 | 82 | if [ "" = "$1" ]; then 83 | break; 84 | fi 85 | 86 | if [ "${arg:0:1}" != "-" ]; then 87 | shift 88 | continue 89 | fi 90 | 91 | case $arg in 92 | -f|--file) 93 | FILE="$2" 94 | shift 2 95 | ;; 96 | 97 | -s|--single) 98 | SINGLE=1 99 | shift 100 | ;; 101 | 102 | -v|--verbose) 103 | VERBOSE=1 104 | shift 105 | ;; 106 | 107 | -h|--help) 108 | usage 1 109 | exit 1 110 | ;; 111 | 112 | -V|--version) 113 | version 114 | exit 0 115 | ;; 116 | 117 | *) 118 | { 119 | echo "unknown option \`$arg'" 120 | } >&$STDERR 121 | usage 122 | exit 1 123 | ;; 124 | esac 125 | done 126 | 127 | opts="" 128 | 129 | if [ "$host" != "$port" ]; then 130 | args="$opts" 131 | cmd="nc $host $port $args" 132 | else 133 | if [ "1" != "$SINGLE" ]; then 134 | opts="$opts -k " 135 | fi 136 | args="$opts-l $port" 137 | cmd="nc $args" 138 | fi 139 | 140 | verbose "args: $args" 141 | 142 | if [ ! -z "$FILE" ]; then 143 | if ! test -f "$FILE"; then 144 | throw "'$FILE' doesn't exist" 145 | fi 146 | fi 147 | 148 | if [ "$host" = "$port" ]; then 149 | MAKEPIPE=1 150 | 151 | pipe="$TMPDIR/_nc_fifo.$host.$port" 152 | rm -f "$pipe" 153 | mkfifo "$pipe" 154 | 155 | verbose "pipe: $pipe" 156 | else 157 | MAKEPIPE=0 158 | fi 159 | 160 | verbose "port: $port" 161 | verbose "cmd: $cmd" 162 | 163 | { 164 | echo 165 | if [ "1" = "$MAKEPIPE" ]; then 166 | while test -p "$pipe"; do 167 | cat $pipe; 168 | done | $cmd | { 169 | trap "echo exit; rm -f $pipe; exit" SIGINT SIGTERM 170 | 171 | while read -r line; do 172 | if [ ! -z "$FILE" ]; then 173 | chunk=`echo "$line" | CHUNK="$line" "$FILE"` 174 | else 175 | chunk="$line" 176 | fi 177 | 178 | if [ "" != "$chunk" ]; then 179 | echo "$chunk" 180 | if [ "1" = "$MAKEPIPE" ]; then 181 | printf "%s\n" "$chunk" >$pipe 182 | fi 183 | fi 184 | done 185 | } 186 | else 187 | while true; do 188 | while read -r chunk; do 189 | if [ ! -z "$FILE" ]; then 190 | chunk=`echo "$chunk" | CHUNK="$chunk" "$FILE"` 191 | fi 192 | 193 | if [ "" != "$chunk" ]; then 194 | echo "$chunk" 195 | fi 196 | $cmd 197 | done < <(echo | $cmd) 198 | done 199 | fi 200 | 201 | } 202 | 203 | rm -f "$pipe" 204 | exit $? 205 | --------------------------------------------------------------------------------