On Github ilyash / ngs-presentation
https://ilyash.github.io/ngs-presentation/
Ilya Sher
Operations & software
Since circa 1987, professionally since 2001
Well, the environment has changed quite a bit.
(From Wikipedia and TLDP.org)
Thompson shell
PWB shell, aka Mashey shell.
Bourne shell is distributed, replacement for Mashey shell.
Later
bash beta v0.99 released
bash 2 adds array variables
bash 3.0 adds built in regular expressions
if [[ "$variable" =~ "your-regex" ]]
bash 4.0
(Personal opinion)
Shell
echo '…' >/etc/apt/sources.list.d/no-product-ads-here.list
Want to try that in Java? (from Stack Overflow, edited)
FileUtils.writeStringToFile( new File("/etc/apt/sources.list.d/no-product-ads-here.list"), "…");
Nginx example - popular alternatives
Nginx Chef cookbook (as of 2015-07, commit e36944b)
Puppet Nginx module (as of 2015-07, commit d1b0908)
Think disregarding the context of this presentation
- Let's try Nginx but I think we will switch to Apache later.
- I know! We need abstraction cookbook!
Is this the right solution?
Scripted. Idempotent code.
The overlap of provided (Chef and Puppet) and required functionality is roughly zero.
… when using Chef or Puppet … because life
if lsof -n | grep -q 'nginx.* 300u';then … service nginx restart … fi if ! pgrep -f 'nginx: master' >/dev/null;then … service nginx start … fi
My definition
Shell language A language that is used by a shell.Python example
Ever wished the compactness of shell scripts be put into a real programming language? -- plumbum project
from plumbum import local ls = local["ls"]
ls()
vs
ls
Python example
ls["-a"] | grep["-v", "\\.py"] | wc["-l"]
vs
ls -a | grep -v '\.py' | wc -l
Non-shell languages are not fit for the job
A real programming language of course
Should be DSL
A shell and a language that
https://github.com/ilyash/ngs
One language
"Power to the people" - the language that implements the shell and the scripting language of the shell should be the same language.
… kind of
Except for editors, how many interactive programs do you really use? We have:
# dd if=/dev/hda … | ssh … _
… and you're blocked.
Should be:
10:23 [56%, 20MB/s, ETA 20m] dd if=/dev/hda … | ssh … # _
dd if=/dev/hda …
Possible heuristic: Has only one open file (except for 0,1,2) to read from, position in /proc/PID/fdinfo/FD
… and add API for progress and status already!
Wrong way: simple instead of right
# apt-cache search ^bash completion bash - … bash-completion - … python-argcomplete - … python3-argcomplete - … # apt-get install <TAB><TAB> Display all 54316 possibilities? (y or n)
Also: why not navigate and pick?
Context / state. Currently only timestamp.
No
ping_output=`$MYADMIN ping 2>&1`; ping_alive=$(( ! $? )) … if [ "$1" = "check_alive" -a $ping_alive = 1 ] || … echo -e "… resulted in\n$ping_output\n"
Yes
ping=$($MYADMIN ping 2>&1) … if mode == 'check_alive' and ping or … echo("… resulted in \n${ping}\n")
syntaxes actually
defg get_all_instances(filters) { if 'VPCID' in ENV { filters.push(['vpc-id', ENV['VPCID']]) } f = mkfilters(filters) instances = ``aws ec2 describe-instances $*f`` .Reservations.Instances.flatten() }
(bad naming stolen from boto)
multi-dispatch (code from stdlib)
# Or throw exception? defg __parse(p:Process) { String(p) } defg __parse(p:Process) { s = String(p) guard s and s[0] == '{' s.from_json() }
if $(-f /etc/debian_version) → if $(test -f /etc/debian_version)
Code from stdlib
defg Bool(p:Process) { p.status == 'exited' and p.code == 0 } … defg '$()'(*args) { guard args.len() > 1 guard startsWith(args[0], '-') args = ['test'] + args # todo: better syntax for this: ($())(*args) }
.Reservations.Instances (code from stdlib)
defg '.'(a:Array, attr:String) { map(a, (.), attr) }
@ wraps the code on the right with lambda
val @ expr → val.map(F(X=null, Y=null, Z=null) { expr })
val @? expr → val.filter(F(X=null, Y=null, Z=null) { expr })
@ expr → F(X=null, Y=null, Z=null) { expr }
Example: val @ expr
echo(5 @ X*2) → echo(5.map(F(x) {x*2}))
outputs
[0, 2, 4, 6, 8]
Example: @ expr
Code from stdlib
defg flatten(s:Seq) { ret = [] s.each(@X.each(@ret.push(X))) ret }
if x==1 { return y }
is
x==1 returns y
code from stdlib + demo
defg map(n:Number, mapper:F, *args) { ret = [] for(i=0;i<n;i=i+1) { ret.push(mapper(i, *args)) } ret }
echo(10.map(F(x) {x*2}))
code from stdlib
defg Number(b:Bool) { if b {1}{0} }
Example 1
my_func(*args)
arr = [1, 2, *args, 3, 4]
Example 2
my_func(**kwargs)
opts = {'my': 'default', **options_i_got, 'my2': 'override'}
Links: