Zx 3.0
github.com
github.com
Great that it's under active development, but changes to my scripts are infrequent and slow. I wouldn't want to be touching an old script on a server somewhere saying "How do I do X in ZX again?" and everything I find online is now for v15 while I'm still on v3.
Maybe if it had plans around a LTS version I'd take a look at that stage.
To be honest though I like doing things in bash. You can get pretty far & it's 100% portable. If something's too complicated for bash it's probably time it's not just a simple CLI script anymore, in my experience.
Would you feel better if they called version three v1.9 instead?
If there are no breaking changes, then I would feel better if they called it v1.9.
Even Go, that prides itself on the good support for parallelism, fails once you actually want go get results back.
If this were paired with some way to also display the status/output of multiple commands in parallel, this would be the ultimate toolkit to write scripts.
If you look at apt, for example: Does it really have to wait for the last package to be downloaded before installing the first? Is there a good reason, on modern SSD-based computers, to not parallelize the installation of multiple packages that don't depend on each other?
somecmd & someothercmd & wait
runs the two commands in parallel and waits for both. no need for await. to run in serial replace & with && and skip the waitStill doesn't let you easily get the output of the two commands, but a good start.
(/my/bg_producer1 > /shm/file1) &
(/my/bg_producer2 > /shm/file2) &
/my/longrunningfgjob
wait
(/my/consumer1 < /shm/file1) &
(/my/consumer2 < /shm/file2) &
wait(If you know how many subshells you started and won't get confused by which is which, you can use `wait -n && wait -n && ...` in bash)
It's doable if you're willing to build a very thin abstraction over whatever you're trying to parallelize keeping in mind all possible edgecases [1] and how you'd like to handle them.
A generic `run N things in parallel and collect their results` function would be nice, but would probably end up being quite unwieldy in comparison to just writing out a purpose-specific function for what you exactly need.
[1] - Error handling, timeouts/cancellation, maximum amount of processes running in parallel, wait-for-full-join vs. returning results as they appear, introspection of currently running subordinates, subordinate output streaming/buffering/logging, ... A lot of things to consider when you're trying to build something universal, but that are easy to solve/ignore when you're building something purpose-specific with known constraints.
Imagine if instead of that, you could do:
foo, bar, []err := await getFoo(), getBar()
if len(err) > 0 {
return nil, nil, fmt.Errorf("Frobnication failed: %s", err)
}
return foo, bar, nil
Of course, JavaScript having exceptions as the main error-raising approach and `await` supporting them makes that a lot easier.IMO, it is pretty much the best-of-all-worlds language that is still accessible. (Meaning not exotic like Haskell or Erlang..)
The concurrency is beautifully painless.
Oh yeah, right, because the first thing that comes to mind when writing bash scripts is "I sure wish there was more 'await' noise in all this code!"
Anyways: 'async' in the Python and Javascript sense was a mistake, future generations will think we were insane to adopt it.
https://journal.stuffwithstuff.com/2015/02/01/what-color-is-...
Adding it to a language where IO is typically blocking with other ergonomic concurrency mechanisms, that I can imagine being somewhat controversial.
It would be good if async weren’t infectious, but as a sibling comment said that was already the case with Promises and callbacks.
It would maybe also be better if concurrency was the default behavior and keeping a reference to a promise was the explicit syntax, but I could see downsides to that. It potentially hides/encourages excessive use of expensive calls. And implicit concurrency is a potential source of many bugs.
It was a terrible idea, as I now had 3 problems instead of 1:
1 - Writing scripts, plus:
2 - Installing Python in every host that needed to run those scripts
3 - Maintaining Python and the necessary dependencies up to date in each host / container.
(2) and (3) are trivial when done just once in your own computer, but end up being a huge time sink for larger heterogeneous environments with (possibly) network and security barriers. Moreover, if you are using containers, installing Python will make images unecessarily large.
Granted, I'm not a JS person, but I imagine one will have the same issues.
Even though bash has its shortcomings, I really appreciate how low maintenance it is as long as you keep scripts small and sane.
My first thought was related to this as well: Perl is _always_ installed, and based on Python's popularity (compared to Perl, at least), I'd assume that Python also was installed by default?
That's an honest question, btw: I use Perl quite a lot, Python not so much (at all). :)
Plus of course if you want to use (pure perl) cpan dependencies I wrote http://p3rl.org/App::FatPacker and http://p3rl.org/Object::Remote to make that easier.
Why do you link to p3rl.org? And, more importantly, why do you link to something that doesn't exist?
For servers it's less common, but enterprise systems never cease to amuse me.
Still, zx isn't as nice as Ruby, which has backticks for calling shell as part of the language. So, you don't have to have a separate package installed, just the ruby runtine.
But Perl is even better! Just like Ruby, it comes with backtick shell execution build-in, but unlike Ruby Perl is ubiquitous and is pretty strict about backward compatibility. So, your scripts will just run on all machines you have, no matter what distro you use and how old the machine is (within reason).
[1] https://github.com/google/zx/blob/3.0.0/test.mjs#L30-L33
Most images will either have bash or ash installed. ash, being lightweight, is the choice of alpine and related distros.
Later shells came in and filled some gaps. OpenBSD still has ksh by default. Linux distros had bash as their /bin/sh.
There could be gray areas where code ownership could be disputed, but in general your employer owns only the intellectual property it paid for.
Source: I'm a Googler (until next month).
Not in the “haha, yes of course”, in the “I’ve spoken to HR and have it writing” kind of way.
I’ve heard this is not true from others, it is simply true in certain geographical regions where local laws override the contract you signed.
That's the catch. Not related to what _you_ do at Google, but related to _anything_ that Google does. Pretty much all the stuff I wanted to work on in my spare time while employed at Google could be seen as related to Google's business/research, as Google does a lot of things. And that's how Google seems to read this too, considering how the Open Sourcing documentation [1] is written.
[1] - https://web.archive.org/web/20210710210932/https://opensourc... “As part of your employment agreement, Google most likely owns intellectual property (IP) you create while at the company. Because Google’s business interests are so wide and varied, this likely applies to any personal project you have. That includes new development on personal projects you created prior to employment at Google.”
Source: I'm a Googler that went through the process before.
Edit #1 for all Googlers reading this: search "IARC" internally and you should land on the proper page to kickstart the process.
Compare e.g. https://thebusinessprofessor.com/en_US/property-law/californ...
I bet Google lacks the copyright for many of the projects they claim.
Good luck taking Google to court.
[1] you fill a form with the general idea description, you explain succinctly why it doesn't compete to any Google product, and you acknowledge you won't use Google time and resources to develop it. Then a committee reviews it and in ~1 week you get your approval or request for more details.
It might work for people who chisel away at their own long-term one-person pet projects, but breaks down if you're used to quickly hacking away collaboratively in various groups. Especially if you're an active member of a hackerspace.
IMHO, such "forced labor for free" is a form of slavery. Slavery is forbidden by law.
If a developer want to publish his project under Google brand, then exchange may be considered as fair (project code for Google branding).
I went through the IARC process 2 years ago for a startup I was about to found in Tokyo, and obtaining clearance was easy, as you say. It's an extra precaution to avoid future litigation, but not legally required if you keep your personal coding activity clearly and provably separate from your work activity.
In some locations, employers can’t claim copyright on works unrelated to your current role.
(Obviously this is not legal advice, talk to your own layers, etc.)
Since they started out owned by Google, you need permission to open source them.
But how much company support they have and how popular they are varies.
There are some exceptions depending on local laws and contracts though, so it’s only mostly and not always true.
https://gist.github.com/zandaqo/93004fb265146a95aadb28ec851a...
Here is a more full fleded version.
`cat package.json | grep name`
branch = `git branch --show-current`
`dep deploy --branch=#{branch}` if $?.success?
[
"sleep 1; echo 1",
"sleep 2; echo 2",
"sleep 3; echo 3",
].map { |cmd| Thread.new { %x(cmd) } }.each(&:join)
name = 'foo bar'
`mkdir /tmp/#{name}` if $?.success?It doesn't matter where input comes from. Input needs to be escaped for the context it's used in, period. Non-exploitable doesn't mean it's correct.
To be safe, abstractions that make it easy to shell out must also:
- escape all variable interpolations by default using “shellwords” or similar.
- throw exceptions on error by default.
Backticks in Ruby are very easy to use, but aren’t safe.
https://ilya-sher.org/2017/01/28/ngs-unique-features-exit-co...
import sh
print(sh.ifconfig("eth0"))
https://amoffat.github.io/sh/> Will Windows be supported?
> There are no plans to support Windows.
If you want the exact opposite of this (that is, to use JS from the shell), try https://bashojs.org
For example:
curl 'https://api.openweathermap.org/data/2.5/weather?q=Bangalore&appid=2a125de83c277f4ce0ace5ed482f22b9' | basho --json -j 'x.weather[0].description + ", feels like: " + Math.round(10 * (x.main.feels_like - 273.15))/10 + "°C"'- Python code with Shell is easier to read ana write
- No nees to carry async/await keywords thru the code
- Powerful plain text manipulation in the stdlib
> Plumbum (Latin for lead, which was used to create pipes back in the day)
Personally, I only see it as the old name for lead. Interesting to see how others are wired.
Not sure how I feel about needing Node.JS to run shell scripts…
Would be a bit more interesting to me if it was a JS shell built from the ground up without the entire mess of the Node package dependency baggage.
If you're working on a Node-based service or React app, you already have to deal with Node and its package ecosystem. Adding a couple of extra MB (or even KB, depending on package reuse) on top of your existing chain of dependencies is a tiny con to the huge benefit of not having to do logic in Bash :)
If you are fluent in Node, it should be easy to avoid further dependencies.
That is pretty subjective
I would recommend using Deno. It has the following advantages:
* Uses Typescript which gives you a great static typing system.
* Runs via V8 so it's about a million times faster than Python.
* Single statically linked binary with no project setup files required (package.json/dependencies.txt) makes it about a million times easier to deploy than either Node or Python. Especially on Windows.
* You can still use third party libraries even without a project file and you get IDE integration.
It's the clear winner at this point. Someone has even made a version of zx for it:
However, situation is similar with nodejs.
Also it obviously depends what your CLI tool is doing. Just because something is a CLI tool doesn't mean it doesn't do much stuff and therefore performance doesn't matter.
For example Scons is a CLI tool. It's a build system written in Python. Everybody abandoned it because it was dog slow.
Mercurial is a CLI tool. It's a VCS written in Python. Most people have abandoned it partly because it is slow (and partly because Github exists).
You can read about Mercurial's troubles with Python performance here:
https://www.mercurial-scm.org/wiki/OxidationPlan
> Performance is a significant pain point with Python. There are multiple facets to the performance problem:
> * Startup overhead
> * General performance overhead compared to native code
> * GIL interfering with parallel execution
> It takes several dozen milliseconds to start a Python interpreter and load the Mercurial Python modules. If you have many extensions loaded, it could take well over 100ms just to effectively get to a Mercurial command's main function. Reports of over 250ms are known. While the command itself may complete in mere milliseconds, Python overhead has already made hg seem non-instantaneous to end-users.
For example if you're using Python to process a lot of files via Make (something my work's build system does unfortunately) then it can end up costing 10s of seconds which is kind of insane.
um… what?
I know a bit of bash, but I'm always looking up how to do things I know are simple in JS. I would love to be able to write scripts in JS because I'm faster with it, and I find it easier to read.
#!/usr/bin/env node
console.log("Hello World!");- https://tc39.es/proposal-hashbang/out.html
- https://github.com/tc39/proposal-hashbang
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
Not saying it doesn't happen, just that it hasn't been my experience.
I think these are some reasons why our mileages differ:
- I need my scripts to work in both Windows and Linux.
- I am not very experienced with bash or other shell.
- Most of my "automation work" only involves reading text from a file, transform it, and write to another file. (Generating SQL commands, doing stats about town names, etc.)
I came across Bash, Powershell, Ruby, Python, Go, Rust, Perl, but JS?
The author of this library has chosen to make the "$" function they provide async; this isn't a JS design feature or limitation, it's just the lib author's choice.
Although this would be fighting the language...
I've seen so many cases of processes being synchronous simply because doing it differently would require an unrealistic amount of custom parallelism code.
You frequently see the same mental mismatch when shell-scripters try to use Python, and complain how hard it is to pipe with POpen, instead of using the built in string processing features.
But in the spirit of "there are only two business models - bundling and unbundling", I guess there are only two marketing tricks: use an old term for a new thing, and introduce a new term for an old thing...
Take that payment system. People who buy things are obviously users, people who write CMS plugins for that system are obviously developers. But what about, say, analysts studying reports from that system? Accountants making sure the money flows where it should? Sysadmins keeping the backend components running? These are all users too.
Where UX makes sense as a broad concept, giving a separate acronym to one small subset of potential users... doesn't make sense.
#!/usr/bin/env zx
#define _ await $
#define __ await Promise.all
#define _1 process.argv[1]
#define _2 process.argv[1]
#define _3 process.argv[1]
_`cat package.json | grep name`
let branch = _`git branch --show-current`
_`dep deploy --branch=${branch}`
__([
$`sleep 1; echo 1`,
$`sleep 2; echo 2`,
$`sleep 3; echo 3`,
])
let name = 'foo bar'
_`mkdir /tmp/${_1}`For this specific use case, they are trying to replace shell scripts. So I thought maybe some people might be willing to consider abbreviations for the async and await keywords for this case.
Maybe I’m just being paranoid.
The node ecosystem is built around having third-party dependencies for everything, which makes it impossible to meaningfully vet the code you're running, and once a dependency gets hijacked, all its dependencies are screwed too.
I usually go with bash + set -euxo pipefail and if it becomes too complicated I switch to Python.
GoLang/Rust are the perfect tool when distributing tools as a single binare. Where in the world does JS fit in?
await $`dep deploy --branch=${branch}`
…
await $`mkdir /tmp/${name}`
Code like this[1] looks prone to shell injectionThey could also be parsing out the first word as the command and not using shell execution at all.
> The zx package provides useful wrappers around child_process, escapes arguments and gives sensible defaults.
lit-html and at least one SQL generating package I've seen use the template string custom interpolation mechanism to auto-escape things - it's a pretty established pattern at this point in javascript land ... but also, yes, until you learn that, it totally does look prone to injection. I've got in the habit of going and finding the template string interpolation function and double checking, because otherwise I find it hard to convince my brain to believe it isn't prone to injection and it interferes with my skim reading the code ;)
I was disappointed this link didn't go to another ZX Spectrum emulator :(
console.log(`Files count: ${count}`)
missing $[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...