https://ilyash.github.io/ngs-presentation/
Ilya Sher
Operations & software
Since circa 1987, professionally since 2001
I think you are going to see, as new environments are developed with new capabilities, scripting capabilities developed around them to make it easy to make them work.-- Steve Bourne, interview to computerworld.com.au, 2009.
Well, the environment has changed quite a bit.
(From Wikipedia and TLDP.org)
Thompson shell
… clear that the Thompson shell was inadequate for most serious programming tasks.
PWB shell, aka Mashey shell.
Bourne shell is distributed, replacement for Mashey shell.
Later
test
#
commentreturn
bash beta v0.99 released
$(…)
command substitution$((math))
calculations<(process substitution)
bash 2 adds array variables
bash 3.0 adds built in regular expressions
if [[ "$variable" =~ "your-regex" ]]
bash 4.0
coproc
**
globbing(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
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: