Skip to content
This repository has been archived by the owner on Dec 4, 2017. It is now read-only.

Commit

Permalink
Improved cli
Browse files Browse the repository at this point in the history
  • Loading branch information
lukasmartinelli committed Mar 25, 2015
1 parent 19b4d6c commit f036189
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 42 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go:
- 1.4
- tip
install:
- go get github.com/andrew-d/go-termutil
- go get github.com/docopt/docopt-go
- go get menteslibres.net/gosexy/redis

54 changes: 32 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,50 @@
# pusred [![Build Status](https://travis-ci.org/lukasmartinelli/pusred.svg)](https://travis-ci.org/lukasmartinelli/pusred)
# redis-pipe [![Build Status](https://travis-ci.org/lukasmartinelli/pusred.svg)](https://travis-ci.org/lukasmartinelli/pusred)

A simple Redis client that connects stdin and stdout with `LPUSH` and `LPOP`.
**redis-pipe** allows you to treat [Redis Lists](http://redis.io/topics/data-types#lists)
as if they were [Unix pipes](https://en.wikipedia.org/wiki/Pipeline_%28Unix%29).
It basically connects `stdin` and `stdout` with `LPUSH` and `LPOP`.

## Examples
## Build

Add value to list
Install dependencies

```
echo "Hello" | ./pusred lpush greetings
go get github.com/andrew-d/go-termutil
go get github.com/docopt/docopt-go
go get menteslibres.net/gosexy/redis
```

Pipe syslog to Redis
Build binary

```
tail -f /var/log/syslog | ./pusred lpush logs
go build redis-pipe.go
```

Read all values from list
## How it works

### Writing from stdin to Redis List

**redis-pipe** takes your values and generates `RPUSH` commands
(generating a valid [Redis protocol](http://redis.io/topics/protocol))
that are then piped into `redis-cli --pipe` ([Redis Mass Insertion](http://redis.io/topics/mass-insert))

### Reading from Redis List to stdout

`LPOP` all the values from the list and write them to `stdout`.

## Examples

### Centralized Logging

In this sample we pipe the syslog to a Redis List called `log`.

```
./pusred lpop greetings
tail -f /var/log/syslog | ./redis-pipe logs
```

## Usage
You can now easily collect all the syslogs of your machines
on a single server.

```
Usage:
pusred lpop <list> [--host=<host>] [--port=<port>]
pusred lpush <list> [--host=<host>] [--port=<port>]
pusred (-h | --help)
Options:
-h --help Show this screen
--host=<host> Redis host [default: localhost]
--port=<port> Redis port [default: 6379]
./redis-pipe logs > logs.txt
```

You can also set the environment variables `RQ_HOST` and `RQ_PORT` to
define the Redis connection.
62 changes: 42 additions & 20 deletions pusred.go → redis-pipe.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,40 +7,57 @@ import (
"os"
"strconv"

"github.com/andrew-d/go-termutil"
"github.com/docopt/docopt-go"
"menteslibres.net/gosexy/redis"
)

const usage string = `
Push and pop values from Redis lists.
Treat Redis Lists like Unix Pipes by connecting stdin with LPUSH
and LPOP with stout.
Usage:
pusred lpop <list> [--host=<host>] [--port=<port>]
pusred lpush <list> [--host=<host>] [--port=<port>]
pusred (-h | --help)
redis-pipe <list> [-n <count>] [--blocking] [--host=<host>] [--port=<port>]
redis-pipe (-h | --help)
Options:
-h --help Show this screen
--blocking Read in blocking mode from list (infinite timeout)
--count=<count> Stop reading from list after count [default: -1]
--host=<host> Redis host [default: localhost]
--port=<port> Redis port [default: 6379]
`

//Pop all values from the given redis list and write the values to stdout
func lpop(list string, client *redis.Client) {
length, _ := client.LLen(list)
for length > 0 {
value, err := client.LPop(list)
func readAll(list string, client *redis.Client, blocking bool) {
for {
read(list, client, 1, blocking)
}
}

func read(list string, client *redis.Client, count int, blocking bool) {
for i := 0; i < count; i++ {
var values []string
var err error

if blocking {
values, err = client.BLPop(0, list)
} else {
values, err = client.BLPop(1, list)
}

if err != nil {
log.Fatalf("Could not LPOP%s: %s\n", list, err.Error())
os.Exit(0)
} else {
fmt.Println(value)
for _, value := range values {
fmt.Println(value)
}
}
length, _ = client.LLen(list)
}
}

//Push all values from stdin to a given redis list
func lpush(list string, client *redis.Client) {
func write(list string, client *redis.Client) {
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
value := scanner.Text()
Expand All @@ -54,8 +71,8 @@ func lpush(list string, client *redis.Client) {
//Return host and port of redis server inferred from either
//environment variables or command line argumentsof redis server
func redisConfig(args map[string]interface{}) (string, uint) {
host := os.Getenv("RQ_HOST")
port := os.Getenv("RQ_PORT")
host := os.Getenv("REDIS_HOST")
port := os.Getenv("REDIS_PORT")

if host == "" {
host = args["--host"].(string)
Expand All @@ -72,20 +89,25 @@ func redisConfig(args map[string]interface{}) (string, uint) {
func main() {
args, _ := docopt.Parse(usage, nil, true, "pusred 0.9", false)
list := args["<list>"].(string)
blockingMode := args["--blocking"].(bool)
host, port := redisConfig(args)
countStr, _ := args["--count"].(string)
count, _ := strconv.ParseInt(countStr, 10, -1)

client := redis.New()
err := client.Connect(host, port)
if err != nil {
log.Fatalf("Connecting to Redis failed: %s\n", err.Error())
}

if args["lpush"].(bool) {
lpush(list, client)
}

if args["lpop"].(bool) {
lpop(list, client)
if termutil.Isatty(os.Stdin.Fd()) {
if count > 0 {
read(list, client, int(count), blockingMode)
} else {
readAll(list, client, blockingMode)
}
} else {
write(list, client)
}

client.Quit()
Expand Down

0 comments on commit f036189

Please sign in to comment.