Given chord length c and segment height m (this is called a "sagitta"),
radius = (m^2 + (c^2)/4) / (2 m)
In OpenSCAD:
c=20;
m=5;
radius=(pow(m,2) + pow(c,2)/4)/(2*m);
https://softsolder.com/2013/08/02/making-finger-grip-dents-the-chord-equation
https://en.wikipedia.org/wiki/Circle#Sagitta
blogodex = {"idx": ["openSCAD", "circle"]};
Monday, July 17, 2017
Wednesday, May 10, 2017
Keys, Primary and Foreign
Welcome to the Bank
Suppose we have an oversimplified banking system, with two tables.
create table balances(name string, balance number);
create table transactions(tid number, from string, to string, amount number);
This allows us to populate a table of people with balances, and transactions where people give money to each other.
balances
name | balance
-----+--------
ann | 200
bob | 150
leo | 300
transactions
tid | from | to | amount
----+------+-----+-------
1 | ann | bob | 25
2 | bob | leo | 50
We can imagine traversing the transaction table something like this pseudocode:
for (from, to, amount) in select("select from,to,amount
from transactions
order by tid")
begin transaction
update balances set balance = balance - amount where name = from;
update balances set balance = balance + amount where name = to;
commit;
(note that sql implementations all vary slightly in how tables and indexes are creates. Everything following is pseudocode.)
Some Data Problems?
Here's a couple of problems we've got in the present system.
Some Data Solutions
1. Let's specify all fields that are required.
create table balances(name string not null, balance number not null);
create table transactions(tid number not null, from string not null,
to string not null, amount number not null);
Now a transaction will fail if we insert a row with a null column. This is nice, because now our code can safely assume we have good non-null data).
2. Specify we can't have duplicate names.
create table balances(name string unique not null, balance number not null);
This will cause an error if we ever
insert into balances(name, balance) values('bob', 100);
insert into balances(name, balance) values('bob', 200);
3. Create some indexes on our key search columns.
create index balances_name_ix on balances(name);
create index transactions_tid_ix on transactions(tid);
Primary Keys
When we look at our tables, we notice that each has a column which serves as the main identifier of a row.
- balances are "owned" by name
- transactions are identified (and ordered) by tid.
We notice three things about these columns.
The concept of a table having a main identifying column, and that column having the three attributes just listed, is so common that we give this a name: That column is the primary key, and can be specified as such.
create table balances(name string primary key, balance number not null);
create table transactions(tid number primary, from string not null,
to string not null, amount number not null);
Declaring a column to be a primary key automatically sets the three things we noticed earlier.
- primary keys are NOT NULL
- primary keys are UNIQUE
- there's an index automatically created for the PK
In addition, via notation we've specified that the row's "identifier" is a particular key... we don't have to guess or infer this information.
Foreign Keys
Let's consider a row in the transactions table:
(1, "ann", "zoo", 50);
If we run this throught the pseudocode above, everything will work and no errors will be reported. But there's a very big problem. This statement is correct,
update balances set balance = balance + amount where name = 'zoo'
but it loses the $50 ann is trying to transfer, since there's no row in balances where name is 'zoo'.
We can solve this in the database by specifying that transactions.from and transactions.to refer to balances.name. Note that semantically this removes the requirement that we declare transactions.from and transactions.to as NOT NULL, since they are required to match balances.name.
create table transactions(tid number primary,
from string references(balances.name),
to string references(balances.name),
amount number not null);
With this in place, this insert will fail:
insert into transactions values(1, 'ann', 'foo', 100);
*** ERROR: foo does not exist in balances(name)
and this delete will fail:
delete from balances where name = 'ann';
*** ERROR: can't delete row with dependencies
There are various options when creating foreign keys, such as ON CASCADE DELETE. In this case,
delete from balances where name = 'ann';
would cause this statement to be implicitly executed as part of the transaction.
delete from transactions where from = 'ann' or to = 'ann';
Caveats
Note that a lot of systems might document the foreign key relations are, but not enforce them in the database, relying instead on programming logic. Sometimes this is done for efficiency (e.g. many inserts into the transactions table -- if you verify from and to are correct, you don't want to pay two lookups penalty on each insert).
A Common PK/FK Idiom
Splitting a potential Fat table into several smaller tables. Sometimes it's for ease of use, sometimes it's for other reasons. For example
create table master_users(uid, Name);
create table billing_info(uid, credit_card, expires, ...);
create table contact_info(uid, address, email, phone, ...);
create table lawsuit_info(uid, ...)
We might be legally required to protect lawsuit_info and not make it visible to people who can see contact info.
In any case, we would make uid a PK in all four tables, allowing us to
# get everyone
select m.name, b.email
from master_users m, billing_info b
where m.uid = b.uid;
# get one person
select m.name, b.email
from master_users m, billing_info b
where m.uid = b.uid and m.uid = 123;
And we could optionally add FK relationships from *_info.uid to master_users.uid.
Suppose we have an oversimplified banking system, with two tables.
create table balances(name string, balance number);
create table transactions(tid number, from string, to string, amount number);
This allows us to populate a table of people with balances, and transactions where people give money to each other.
balances
name | balance
-----+--------
ann | 200
bob | 150
leo | 300
transactions
tid | from | to | amount
----+------+-----+-------
1 | ann | bob | 25
2 | bob | leo | 50
We can imagine traversing the transaction table something like this pseudocode:
for (from, to, amount) in select("select from,to,amount
from transactions
order by tid")
begin transaction
update balances set balance = balance - amount where name = from;
update balances set balance = balance + amount where name = to;
commit;
(note that sql implementations all vary slightly in how tables and indexes are creates. Everything following is pseudocode.)
Some Data Problems?
Here's a couple of problems we've got in the present system.
- We can have empty (null) fields. For example, a transaction of insert (3,bob,NULL,NULL).
- We can have duplicate people in the balance table. Note that it's OK if balances are duplicated (you and I can have the same amount of money!) but each person must be unique.
- We are going to be performing lookups keyed by transactions.tid and balances.name. We better make that efficient if we're going to grow to be a bank with millions of users and transactions!
Some Data Solutions
1. Let's specify all fields that are required.
create table balances(name string not null, balance number not null);
create table transactions(tid number not null, from string not null,
to string not null, amount number not null);
Now a transaction will fail if we insert a row with a null column. This is nice, because now our code can safely assume we have good non-null data).
2. Specify we can't have duplicate names.
create table balances(name string unique not null, balance number not null);
This will cause an error if we ever
insert into balances(name, balance) values('bob', 100);
insert into balances(name, balance) values('bob', 200);
3. Create some indexes on our key search columns.
create index balances_name_ix on balances(name);
create index transactions_tid_ix on transactions(tid);
Primary Keys
When we look at our tables, we notice that each has a column which serves as the main identifier of a row.
- balances are "owned" by name
- transactions are identified (and ordered) by tid.
We notice three things about these columns.
- they should never be null (because they identify the row)
- they should be unique (because it doesn't make sense for them to be dupes)
- practically, they should have an index (because we usually use them in where clauses).
The concept of a table having a main identifying column, and that column having the three attributes just listed, is so common that we give this a name: That column is the primary key, and can be specified as such.
create table balances(name string primary key, balance number not null);
create table transactions(tid number primary, from string not null,
to string not null, amount number not null);
Declaring a column to be a primary key automatically sets the three things we noticed earlier.
- primary keys are NOT NULL
- primary keys are UNIQUE
- there's an index automatically created for the PK
In addition, via notation we've specified that the row's "identifier" is a particular key... we don't have to guess or infer this information.
Foreign Keys
Let's consider a row in the transactions table:
(1, "ann", "zoo", 50);
If we run this throught the pseudocode above, everything will work and no errors will be reported. But there's a very big problem. This statement is correct,
update balances set balance = balance + amount where name = 'zoo'
but it loses the $50 ann is trying to transfer, since there's no row in balances where name is 'zoo'.
We can solve this in the database by specifying that transactions.from and transactions.to refer to balances.name. Note that semantically this removes the requirement that we declare transactions.from and transactions.to as NOT NULL, since they are required to match balances.name.
create table transactions(tid number primary,
from string references(balances.name),
to string references(balances.name),
amount number not null);
With this in place, this insert will fail:
insert into transactions values(1, 'ann', 'foo', 100);
*** ERROR: foo does not exist in balances(name)
and this delete will fail:
delete from balances where name = 'ann';
*** ERROR: can't delete row with dependencies
There are various options when creating foreign keys, such as ON CASCADE DELETE. In this case,
delete from balances where name = 'ann';
would cause this statement to be implicitly executed as part of the transaction.
delete from transactions where from = 'ann' or to = 'ann';
Caveats
Note that a lot of systems might document the foreign key relations are, but not enforce them in the database, relying instead on programming logic. Sometimes this is done for efficiency (e.g. many inserts into the transactions table -- if you verify from and to are correct, you don't want to pay two lookups penalty on each insert).
A Common PK/FK Idiom
Splitting a potential Fat table into several smaller tables. Sometimes it's for ease of use, sometimes it's for other reasons. For example
create table master_users(uid, Name);
create table billing_info(uid, credit_card, expires, ...);
create table contact_info(uid, address, email, phone, ...);
create table lawsuit_info(uid, ...)
We might be legally required to protect lawsuit_info and not make it visible to people who can see contact info.
In any case, we would make uid a PK in all four tables, allowing us to
# get everyone
select m.name, b.email
from master_users m, billing_info b
where m.uid = b.uid;
# get one person
select m.name, b.email
from master_users m, billing_info b
where m.uid = b.uid and m.uid = 123;
And we could optionally add FK relationships from *_info.uid to master_users.uid.
Thursday, November 24, 2016
Arduino Stepper with ULN2003 driver
// stepper1 -- repeat 1 CW and CCW revolution
/*
https://arduino-info.wikispaces.com/SmallSteppers
5v 28YBJ-48 Stepper Motor with Gear Reduction
ULN2003 driver board
*/
#include
// internal motor steps per revolution in 4-step mode
#define STEPS_PER_MOTOR_REVOLUTION 32
// steps per OUTPUT SHAFT of gear reduction
#define STEPS_PER_OUTPUT_REVOLUTION (STEPS_PER_MOTOR_REVOLUTION*64)
//The pin connections need to be 4 pins connected
// to Motor Driver In1, In2, In3, In4 and then the pins entered
// here in the sequence 1-3-2-4 for proper sequencing
Stepper s(STEPS_PER_MOTOR_REVOLUTION, 8, 10, 9, 11);
void setup()
{
s.setSpeed(500); // 700 good max?
}
void loop()
{
s.step(2 * STEPS_PER_OUTPUT_REVOLUTION); // CW 1 turn
s.step(-STEPS_PER_OUTPUT_REVOLUTION); // CCW 1 turn
delay(500);
}
/*
https://arduino-info.wikispaces.com/SmallSteppers
5v 28YBJ-48 Stepper Motor with Gear Reduction
ULN2003 driver board
*/
#include
// internal motor steps per revolution in 4-step mode
#define STEPS_PER_MOTOR_REVOLUTION 32
// steps per OUTPUT SHAFT of gear reduction
#define STEPS_PER_OUTPUT_REVOLUTION (STEPS_PER_MOTOR_REVOLUTION*64)
//The pin connections need to be 4 pins connected
// to Motor Driver In1, In2, In3, In4 and then the pins entered
// here in the sequence 1-3-2-4 for proper sequencing
Stepper s(STEPS_PER_MOTOR_REVOLUTION, 8, 10, 9, 11);
void setup()
{
s.setSpeed(500); // 700 good max?
}
void loop()
{
s.step(2 * STEPS_PER_OUTPUT_REVOLUTION); // CW 1 turn
s.step(-STEPS_PER_OUTPUT_REVOLUTION); // CCW 1 turn
delay(500);
}
Saturday, November 5, 2016
Friday, November 4, 2016
Arduino Encryption
I've been looking at encryption libraries that would run on an Arduino. This looks like something worth looking into.
https://github.com/abderraouf-adjal/ArduinoSpritzCipher
https://people.csail.mit.edu/rivest/pubs/RS14.pdf
This library contains a cryptographic pseudo-random number generator, cryptographic hash and message authentication code (MAC) functions, can perform symmetric-key authenticated data encryption, and general-purpose functions for timing-safe comparison and wiping data from memory.https://hackaday.io/project/8244-arduino-spritz-cipher-library
https://github.com/abderraouf-adjal/ArduinoSpritzCipher
https://people.csail.mit.edu/rivest/pubs/RS14.pdf
Monday, September 12, 2016
Vim + Go + Mac
There's a lot of notes written for getting Vim + Go up and running, but a lot of the notes assume you're already in modern Vim-land. Here's what I did to get up and going from scratch.
cd $HOME
rm -rf .vim .vimrc .viminfo
brew install macvim --with-cscope --with-lua --override-system-vim
set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin()
filetype plugin indent on
And move all the directories into .vim. It seems there should be and easier way to do this... ping me if you know what it is!
Plugin 'fatih/vim-go'
0. Start off with a totally clean vim configuration.
Save off your current files/setting if they're important to you.cd $HOME
rm -rf .vim .vimrc .viminfo
1. Install a vim with lua support.
I think the easiest way to do this is to install the latest macvim from Homebrew. If you're a developer on Mac, Homebrew is well worth looking into.brew install macvim --with-cscope --with-lua --override-system-vim
brew linkapps macvim
brew install vim --with-lua --override-system-vim
2. Install Vundle
There's a couple of Vim package managers. I don't know enough about Vim package management to recommend one over another, but Vundle seems to be pretty popular.
git clone https://github.com/VundleVim/Vundle.vim ~/.vim/bundle/Vundle.vim
Here's the minimal .vimrc needed to get bootstrapped.
set nocompatible
filetype off
set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin()
Plugin 'VundleVim/Vundle.vim'
"Plugin 'Valloric/YouCompleteMe' reserve for step 3 below
"Plugin 'fatih/vim-go' <------- font="" nbsp="">reserve for step 4 below------->
call vundle#end()
filetype plugin indent on
Restart vim and install the plugins with the command
:PluginInstall
3. Install YouCompleteMe
This require you install XCode from Apple. Start off by installing cmake.
brew install cmake
Install YouCompleteMe and pull in submodules.
cd ~/.vim/bundle
git clone git@github.com:Valloric/YouCompleteMe.git
cd ~/.vim/bundle/YouCompleteMe
git submodule update --init --recursive
Build YouCompleteMe
cd ~/.vim/bundle/YouCompleteMe
./install.py --gocode-completer
Make sure ~/.vimrc has the line
Plugin 'Valloric/YouCompleteMe'
Restart vim and install the plugin as we did above
:PluginInstall
4. Install Vim-Go
Download the latest release from https://github.com/fatih/vim-go/releases and untar it.
cd /tmp
curl -s https://codeload.github.com/fatih/vim-go/tar.gz/v1.8 | tar xf -
And move all the directories into .vim. It seems there should be and easier way to do this... ping me if you know what it is!
(cd /tmp/vim-go-1.8; tar cf - autoload compiler doc \
ftdetect ftplugin gosnippets indent plugin scripts syntax t templates) |
(cd ~/.vim; tar xf -)
Then add to .vimrc
Restart vim and run
:PluginInstall
Tuesday, August 30, 2016
Mapping Ctrl, CapsLock Tap to Esc
Now you can vi just as Bill Joy intended! Here's an article that makes tapping the control key send an Esc.
Setting up ssh for github
On Mac and Linux, set up an ssh key in the usual way:
ssh-keygen
cat $HOME/.ssh/id_rsa.pub
Copy that into the github ssh keylist.
Linux: start the ssh agent. This will be good for the duration of the session.
exec ssh-agent bash
ssh-add
Mac: add the ssh key to the keychain. This only needs to be done once.
ssh-add
To test your connection to github.
ssh -T git@github.com
ssh-keygen
cat $HOME/.ssh/id_rsa.pub
Copy that into the github ssh keylist.
Linux: start the ssh agent. This will be good for the duration of the session.
exec ssh-agent bash
ssh-add
Mac: add the ssh key to the keychain. This only needs to be done once.
ssh-add
To test your connection to github.
ssh -T git@github.com
Saturday, July 23, 2016
Saturday, July 2, 2016
Some Interesting Go Videos
Using Go at The New York Times
Twelve Go Best Practices - Francesc Campoy
Google I/O 2013 - Fireside Chat with the Go Team
Origins of Go Concurrency style by Rob Pike
Google I/O 2012 - Go Concurrency Patterns
Rob Pike - 'Concurrency Is Not Parallelism'
Google I/O 2013 - Advanced Go Concurrency Patterns
Go for Pythonistas
Go Proverbs - Rob Pike - Gopherfest - November 18, 2015
Building Services in Go
Let's Go Further: Build Concurrent Software using the Go Programming Language
The Go Programming Language - Rob Pike
A Tour of the Go Programming Language with Russ Cox
blogodex = {"toc" : "golang", "idx" : "videos"};
Sunday, June 26, 2016
Interesting Python One-Liners
You can do some amazing things with lambda and itertools.
Python one-lines for Project Euler
Half of linear algebra in 10 Python one-liners
KNN classifier in one line of Python
blogodex = {"toc" : "one-liners", "idx" : "Python"};
Python one-lines for Project Euler
Half of linear algebra in 10 Python one-liners
KNN classifier in one line of Python
blogodex = {"toc" : "one-liners", "idx" : "Python"};
Thursday, June 23, 2016
GitHub based dotfiles
Not much new here, this is just my take on StreakyCobra's excellent work, with these differences:
- I made two repos, one for dotfiles, one for scripts that go into $HOME/bin.
- I made two commands dotf and binf that correspond to StreakyCobra's config.
- incorporated github repos dotf and binf as noted.
# create github repo "dotf"
git init --bare $HOME/.dotf
alias dotf='/usr/bin/git --git-dir=$HOME/.dotf/ --work-tree=$HOME'
dotf config status.showUntrackedFiles no
dotf add .bash_profile
dotf commit -m "first import"
dotf remote add origin git@github.com:YOURNAME/dotf.git
dotf push -u origin master
# create github repo "binf"
git init --bare $HOME/.binf
alias binf='/usr/bin/git --git-dir=$HOME/.binf --work-tree=$HOME/bin'
# binf config status.showUntrackedFiles no ## want to track unused files
cd $HOME/bin
dotf add some-file
dotf commit -m "first import"
binf remote add origin git@github.com:YOURNAME/binf.git
binf push -u origin master
git init --bare $HOME/.dotf
alias dotf='/usr/bin/git --git-dir=$HOME/.dotf/ --work-tree=$HOME'
dotf config status.showUntrackedFiles no
dotf add .bash_profile
dotf commit -m "first import"
dotf remote add origin git@github.com:YOURNAME/dotf.git
dotf push -u origin master
# create github repo "binf"
git init --bare $HOME/.binf
alias binf='/usr/bin/git --git-dir=$HOME/.binf --work-tree=$HOME/bin'
# binf config status.showUntrackedFiles no ## want to track unused files
cd $HOME/bin
dotf add some-file
dotf commit -m "first import"
binf remote add origin git@github.com:YOURNAME/binf.git
binf push -u origin master
Wednesday, June 15, 2016
Do you have a restless urge to program?
I finally found a scan advertising the Famous Programmers' School which originally appeared in the April 1982 of BYTE, page 384.
"Top down programming for the masses."
"Top down programming for the masses."
Friday, May 13, 2016
Adding a git commit template
So I find myself constantly forgetting to add the jira ticket number to commits that need them.
echo JIRA >~/txt/git-commit-template.txt
And one of these commands
git config commit.template ~/txt/git-commit-template.txt
Don't forget to manage your git commit template in git!
echo JIRA >~/txt/git-commit-template.txt
And one of these commands
git config commit.template ~/txt/git-commit-template.txt
git config --global commit.template ~/txt/git-commit-template.txt
or put in in .git/config (per repo) or $HOME/.gitconfig (global):
[commit]
template = /Users/mh/txt/git-commit-template.txt
blogodex = {"toc" : "git", "idx" : "commit template"};
Friday, April 29, 2016
Python: virtualenv quickstart
Installation
pip install virtualenv
Usage
mkdir myproject
cd myproject
pip install virtualenv
Usage
mkdir myproject
cd myproject
virtualenv foo
source foo/bin/activate
pip install hjson # install packages...
./foo/bin/python
import hjson
./foo/bin/python
import hjson
Getting pip if necessary
curl -o get-pip.py https://bootstrap.pypa.io/get-pip.py
python get-pip
yum install openssl openssl-devel
or
apt-get install openssl openssl-devel
References
https://pip.pypa.io/en/stable/installing/
http://docs.python-guide.org/en/latest/dev/virtualenvs/
Getting ssl if necessary in order to get pip on your linux box
symptom: ImportError: cannot import name HTTPSHandler
or
apt-get install openssl openssl-devel
References
https://pip.pypa.io/en/stable/installing/
http://docs.python-guide.org/en/latest/dev/virtualenvs/
Wednesday, April 27, 2016
Encrypting UDP Game Traffic
not only encryption protects your players from classical attacks, it also protects your games against cheaters too.
As a side bonus, with proper encryption you can be sure that network errors which corrupt your packets are not going undetected (and with unencrypted UDP those 16-bit UDP checksums can detect only one out of 60’000 in-transit corruptions, which means that with all those millions of packets you’re sending out each second, some corruptions WILL go undetected, causing all kinds of trouble).
http://ithare.com/udp-for-games-security-encryption-and-ddos-protection/
Tuesday, April 19, 2016
Classic Programmer Paintings!
http://classicprogrammerpaintings.tumblr.com
My Favorite:
Hieronymus Bosch “A visual guide to the Scala language” oil on oak panels, 1490-1510.
The left panel shows the functional features, the main one describes the type system, and the right the object oriented parts.
My Favorite:
Hieronymus Bosch “A visual guide to the Scala language” oil on oak panels, 1490-1510.
The left panel shows the functional features, the main one describes the type system, and the right the object oriented parts.
Friday, March 18, 2016
brewing mysql / binlog reader
Here's what I did to set up MySQL 5.6 on my Mac in binlog row mode, prepping to talk to Aurora.
+1 for brew services!
Install and Test
brew install mysql56
brew tap homebrew/services
brew services start mysql56
mysqladmin -uroot create mh
mysql -uroot
+1 for brew services!
Install and Test
brew install mysql56
brew tap homebrew/services
brew services start mysql56
mysqladmin -uroot create mh
mysql -uroot
Find my.cnf
/usr/local/bin/mysqld --verbose --help 2>/dev/null | grep -A 1 "Default options"
Default options are read from the following files in the given order:
/etc/my.cnf /etc/mysql/my.cnf /usr/local/etc/my.cnf ~/.my.cnf
Default options are read from the following files in the given order:
/etc/my.cnf /etc/mysql/my.cnf /usr/local/etc/my.cnf ~/.my.cnf
Configuring binary logging
$ cat /usr/local/etc/my.cnf
[mysqld]
log-bin=mysql-bin
binlog_format=row
server-id=1235
mysql> show binary logs;
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000001 | 143 |
| mysql-bin.000002 | 120 |
+------------------+-----------+
[mysqld]
log-bin=mysql-bin
binlog_format=row
server-id=1235
binlog status
Restart mysql and you can see the logs and current position.
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000001 | 143 |
| mysql-bin.000002 | 120 |
+------------------+-----------+
mysql> show master status;
+----------------+----------+-
| File | Position |
+----------------+----------+- . . .
| mysql-bin.000002 | 1309
+----------------+----------+-
Tailing the binlog
mysqlbinlog --read-from-remote-server --host=localhost mysql-bin.000001 -uroot -v --stop-never
Insert some data like this
mysql> insert into t values(99);
and you'll see it come out like this
# at 1309
#160318 11:40:42 server id 1235 end_log_pos 1379 CRC32 0xaf303ba0 Query thread_id=7 exec_time=0 error_code=0
SET TIMESTAMP=1458326442/*!*/;
BEGIN
/*!*/;
# at 1379
#160318 11:40:42 server id 1235 end_log_pos 1421 CRC32 0xb302b235 Table_map: `mh`.`t` mapped to number 70
# at 1421
#160318 11:40:42 server id 1235 end_log_pos 1461 CRC32 0x4d9e5013 Write_rows: table id 70 flags: STMT_END_F
BINLOG '
qkvsVhPTBAAAKgAAAI0FAAAAAEYAAAAAAAEAAm1oAAF0AAEDAAE1sgKz
qkvsVh7TBAAAKAAAALUFAAAAAEYAAAAAAAEAAgAB//5jAAAAE1CeTQ==
'/*!*/;
### INSERT INTO `mh`.`t`
### SET
### @1=99
# at 1461
#160318 11:40:42 server id 1235 end_log_pos 1492 CRC32 0x94dcc720 Xid = 73
COMMIT/*!*/;
blogodex = {"toc" : "MySQL binlog", "idx" : ["MySQL","binlog","configuration"]};
Thursday, March 17, 2016
brew services
You can use brew to interface with launchservices. It's great!
Setup:
- brew tap homebrew/services
Usage:
- brew services list
- brew services start etcd
- brew services restart etcd
- brew services stop etcd
Lots of details over at thoughtbot!
blogodex = {"toc" : "brew", "idx" : ["services", "launchd"]};
Subscribe to:
Posts (Atom)
-
A while back I answered a question on Stack Overflow asking about the relative popularity of The Art of Computer Programming . I replied wit...
-
Here's a quick example of duckdb's new ASOF JOIN. Problem: we have a time-based price table; if you have a sale time that falls in t...
-
Covering: Introducing Kafka: history, Kafka at LinkedIn, Kafka adoption in the industry, why Kafka Kafka core concepts: topics, partiti...



