How to read barcodes with ZXing and ZBar

Tagged barcode, code 39, data matrix, qr code, zbar, zxing  Languages bash

How to read barcodes

$ java -cp javase.jar:core.jar com.google.zxing.client.j2se.CommandLineRunner barcode.png --try_harder --format=DATA_MATRIX
$ zbarimg barcode.png

Note that cropping might improve detection accuracy. For example, crop image to show only the top-right corner using imagemagick’s convert (width 1500, height 500):

$ convert example.png -gravity northeast -crop 1500x500+0+0 cropped.png

NOTE

  • if you need data correction (reliability) use a Data Matrix (used on e.g. products), Aztec (used on e.g. tickets), or QR code. These allow up to 30% of the image to be unreadable.
  • do not use a barcode that uses code 39 or 128. There is no error correction in code 39 and 128.
  • SimpleCV can also be used to detect barcodes.

Log shipping with rsyslog

Tagged logging, logs, remote, rsyslog, shipping  Languages 

Server

/etc/rsyslog.conf

$ModLoad imtcp
 
#
# Disable rate-limiting
#
# "interval = 1 AND burst = 1000" means rsyslog starts dropping messages if more than 1000 messages are received within 1 seconds. 
$SystemLogRateLimitInterval 0
$SystemLogRateLimitBurst 0

/etc/rsyslog.d/35-remote-logs.conf

input(type="imtcp" port="514" ruleset="remote")
template(name="PerRemoteHostLogFileName" type="list") {
   constant(value="/var/log/hosts/")
   property(name="$year")
   constant(value="/")
   property(name="$month")
   constant(value="/")
   property(name="hostname" securepath="replace")
   constant(value="/")
   property(name="programname" securepath="replace")
   constant(value=".log")
}
ruleset(name="remote") {
   $FileCreateMode 0640
   $DirCreateMode 0755
   ?PerRemoteHostLogFileName
}

Client

/etc/rsyslog.conf

# Disable rate-limiting
$SystemLogRateLimitInterval 0
$SystemLogRateLimitBurst 0

#
# Send all logs to centralized log server over TCP
#
*.*       @@{{log_server_ip_addr}}

How to deploy an app on a specific node/server in a kubernetes cluster using labels

Tagged kubernetes, label, node  Languages yaml

This is an example of how to deploy an app on a specific node/server in a kubernetes cluster using labels:

# # Label one node in k8s cluster
#
# $ kubectl label nodes 48.234.16.45 country=finland name=node1
#
# # Deploy 1 nginx pod in k8s cluster on node1 in Finland
#
# $ kubectl apply -f nginx.yml
#
# # View deployment
#
# $ kubectl describe deployment nginx-app
#
# # View pods
#
# $ kubectl get pods -l app=nginx
#
# # Find port the service is listening on
#
# $ kubectl describe service nginx-app | grep NodePort
# > NodePort:                 http   31796/TCP
# > NodePort:                 https  31797/TCP
#
# # Find the node the pod is deployed to
#
# $ kubectl describe pods nginx-app | grep Node
# > Node:           48.234.16.45/10.0.0.2
#
# # Access deployment using node ip and port
#
# http://<node ip>:<node port>
#
# # Export service to YAML
#
# $ kubectl get service nginx-app -o yaml --export
#
# # Delete
#
# $ kubectl delete deployments,services -l country=finland
#
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-app
  labels:
    run: nginx-app
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1 # tells deployment to run 1 pods matching the template
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.13.12
        ports:
        - containerPort: 80
        - containerPort: 443
      nodeSelector:
        country: finland
        server: node1
---
#
# Expose deployment on <node ip>:<node port>. Node and a random port is assigned by k8s.
#
apiVersion: v1
kind: Service
metadata:
  labels:
    run: nginx-app
  name: nginx-app
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
  - name: https
    port: 443
    protocol: TCP
    targetPort: 443
  selector:
    app: nginx
  type: NodePort

Kill OSX disk warning notification

Tagged kill, notification, osx  Languages bash

Kill OSX disk warning notification:

$ defaults write com.apple.diskspaced minFreeSpace 1

This prevents it from showing up every second, if free disk space is above 1 Gb.

How to SSH with Go

Tagged go, ssh  Languages go, bash

How to SSH with Go.

main.go:

package main

import (
    "bytes"
    "flag"
    "golang.org/x/crypto/ssh"
    "io/ioutil"
    "log"
    "os"
    "strings"
)

var host string
var port string
var user string
var command string
var keyPath string
var keyPass string

func init() {
    flag.StringVar(&host, "host", "", "SSH hostname or IP")
    flag.StringVar(&port, "port", "", "SSH port")
    flag.StringVar(&user, "user", "", "SSH user")
    flag.StringVar(&command, "command", "", "Command to execute on server")
    flag.StringVar(&keyPath, "key-path", "", "For example, ~/.ssh/id_rsa")
    flag.StringVar(&keyPass, "key-password", "", "Password for private key (optional)")
    flag.Parse()
    if host == "" || port == "" || command == "" || user == "" || keyPath == "" {
        flag.PrintDefaults()
        os.Exit(2)
    }
}

func readPubKey(file string) ssh.AuthMethod {
    var key ssh.Signer
    var err error
    var b []byte
    b, err = ioutil.ReadFile(file)
    mustExec(err, "failed to read public key")
    if !strings.Contains(string(b), "ENCRYPTED") {
        key, err = ssh.ParsePrivateKey(b)
        mustExec(err, "failed to parse private key")
    } else {
        key, err = ssh.ParsePrivateKeyWithPassphrase(b, []byte(keyPass))
        mustExec(err, "failed to parse password-protected private key")
    }
    return ssh.PublicKeys(key)
}

func main() {
    conf := &ssh.ClientConfig{
        User: user,
        Auth: []ssh.AuthMethod{
            readPubKey(keyPath),
        },
        HostKeyCallback: ssh.InsecureIgnoreHostKey(), // XXX: Security issue
    }
    client, err := ssh.Dial("tcp", strings.Join([]string{host, ":", port}, ""), conf)
    mustExec(err, "failed to dial SSH server")
    session, err := client.NewSession()
    mustExec(err, "failed to create SSH session")
    defer session.Close()
    var b bytes.Buffer
    session.Stdout = &b
    err = session.Run(command)
    mustExec(err, "failed to run command over SSH")
    log.Printf("%s: %s", command, b.String())
}

func mustExec(err error, msg string) {
    if err != nil {
        log.Fatalf("%s:\n  %s", msg, err)
    }
}

This command will run a command on a remote SSH server:

go run main.go -command whoami -host bush.com -key-path ~/.ssh/id_rsa -port 22 -user jeb

Also see:

Repeatable-read vs read-committed example in Rails / ActiveRecord

Tagged isolation, postgres, read-commited, repeatable-read, transaction, activerecord, rails  Languages ruby
ActiveRecord::Base.logger = Logger.new(STDOUT)

require "test/unit/assertions"
include Test::Unit::Assertions

class Cust1 < ActiveRecord::Base
  self.table_name = "customers"
end

class Cust2 < ActiveRecord::Base
  self.table_name = "customers"
end

# NOTE: Two separate connections
Cust1.establish_connection :development
Cust2.establish_connection :development

Cust1.find_by(username: 'z@localhost').try(:delete)

c = Cust1.create!(first_name: 'Putin', last_name: 'jebus', password_digest: 'abcdef12345', username: 'z@localhost')

case ENV['isolation']
when 'repeatable_read'
  #
  # NOTE: Repeatable-read isolation
  #
  # This level is different from Read Committed in that a query in a repeatable
  # read transaction sees a snapshot as of the start of the transaction, not as
  # of the start of the current query within the transaction. Thus, successive
  # SELECT commands within a single transaction see the same data, i.e., they do
  # not see changes made by other transactions that committed after their own
  # transaction started.
  #
  puts "Repeatable read"
  assert ActiveRecord::Base.connection.transaction_isolation_levels.include?(:repeatable_read)
  Cust1.transaction(isolation: :repeatable_read) do
    c.reload
    Cust2.find(c.id).update_attributes(first_name: 'Stalin')
    c.reload
    assert_equal 'Putin', c.first_name
  end
  c.reload
  assert_equal 'Stalin', c.first_name
else
  #
  # NOTE: Read-committed isolation
  #
   # Read Committed is the default isolation level in PostgreSQL. When a
  # transaction uses this isolation level, a SELECT query (without a FOR
  # UPDATE/SHARE clause) sees only data committed before the query began; it
  # never sees either uncommitted data or changes committed during query
  # execution by concurrent transactions. In effect, a SELECT query sees a
  # snapshot of the database as of the instant the query begins to run.
  # However, SELECT does see the effects of previous updates executed within
  # its own transaction, even though they are not yet committed. Also note that
  # two successive SELECT commands can see different data, even though they are
  # within a single transaction, if other transactions commit changes after the
  # first SELECT starts and before the second SELECT starts.
  #
  puts "Read committed"
  Cust1.transaction do
    c.reload
    Cust2.find(c.id).update_attributes(first_name: 'Stalin')
    c.reload
    assert_equal 'Stalin', c.first_name
  end
  c.reload
  assert_equal 'Stalin', c.first_name
end

See

Rounding to the nearest range with modulo

Tagged modulo, range  Languages ruby
require 'pp'
hash = Hash.new {|h,k| h[k] = [] }
(0..99).step(5).each do |num|
  # XXX: 10 - 10%10 => 10
  range = num - num%10
  hash[range] << num
end
pp hash

{0=>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
 10=>[10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
 20=>[20, 21, 22, 23, 24, 25, 26, 27, 28, 29],
 30=>[30, 31, 32, 33, 34, 35, 36, 37, 38, 39],
 40=>[40, 41, 42, 43, 44, 45, 46, 47, 48, 49],
 50=>[50, 51, 52, 53, 54, 55, 56, 57, 58, 59],
 60=>[60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
 70=>[70, 71, 72, 73, 74, 75, 76, 77, 78, 79],
 80=>[80, 81, 82, 83, 84, 85, 86, 87, 88, 89],
 90=>[90, 91, 92, 93, 94, 95, 96, 97, 98, 99]}

Fetch the status of Postgres' streaming replication with ActiveRecord and Rails

Tagged pg_current_wal_flush_lsn, pg_last_wal_receive_lsn, postgres, replication, streaming  Languages ruby

When using streaming replication you can use this code to fetch the number of bytes the slave is behind the master in applying changes to the WAL (write-ahead log):

class SlaveDatabase < ApplicationRecord
  self.abstract_class = true
  # NOTE: Add slave entry to config/database.yml
  establish_connection :slave

  #
  # Returns the number of bytes the slave is behind the master in applying WAL updates.
  #
  def self.replication_delta
    # Returns, for example, 12/547C3A58 from the master
    current_master_wal = ActiveRecord::Base.connection.select_value("SELECT pg_current_wal_flush_lsn();")
    # Returns, for example, -7504582 from the slave
    delta = connection.select_value("SELECT #{connection.quote(current_master_wal)} - pg_last_wal_receive_lsn()")
    raise "pg_last_wal_receive_lsn returned null, see documentation for details" unless delta
    Integer(delta).abs
  end
end

Tested with version Postgres 10. Note that in version 10, pg_last_xlog_receive_location has been renamed to pg_last_wal_receive_lsn, and pg_current_xlog_flush_location has been renamed to pg_current_wal_flush_lsn.

Pagination in ActiveRecord and SQL

Tagged activerecord, pagination  Languages ruby, slim

How to do pagination in ActiveRecord and SQL without any external dependencies.

Code:

class Pagination
  PER_PAGE ||= 10
  def self.call(relation:, page: 0, per_page: PER_PAGE)
    page = page.to_i
    per_page = per_page.to_i
    offset = page*per_page
    array = relation.offset(offset).limit(per_page+1).to_a
    row_count = relation.count
    page_count = (row_count.to_f / per_page.to_f).ceil
    has_previous_page = page > 0
    has_next_page = array.size > per_page
    pagination = OpenStruct.new(
      page: page,
      page_count: page_count,
      previous_page: has_previous_page ? page - 1 : nil,
      next_page: has_next_page ? page + 1 : nil
    )
    array = array[0..-2] if has_next_page
    [ array, pagination ]
  end
end

Example:

let(:relation) { Measurement.order("created_at DESC") }

it "paginates" do
  measurements, pagination = Pagination.call(relation: relation, per_page: 1, page: 0)
  assert_equal 1, measurements.size
  assert_equal OpenStruct.new(page: 0, page_count: 1, previous_page: nil, next_page: nil), pagination
end

View:

- if @pagination.previous_page || @pagination.next_page
  .pagination
    ul
      - if @pagination.previous_page
        li
          a href=url_for(params.merge(page: nil)) ‹
        li
          a href=url_for(params.merge(page: @pagination.previous_page)) = t('previous')
        - ([0, @pagination.page-4].max..@pagination.page-1).each do |page|
          li
            a href=url_for(params.merge(page: page)) #{page+1}
      - else
        li
          span.muted ‹
        li
          span.muted = t('previous')
      li
        span.muted #{t('page')} #{@pagination.page + 1}
      - if @pagination.next_page
        - (@pagination.page+1..[@pagination.page_count-1, @pagination.page+4].min).each do |page|
          li
            a href=url_for(params.merge(page: page)) #{page+1}
        li
          a href=url_for(params.merge(page: @pagination.next_page)) = t('next')
        li
          a href=url_for(params.merge(page: @pagination.page_count - 1)) ›
      - else
        li
          span.muted = t('next')