Hacker News new | ask | show | jobs
by voidz 3716 days ago
A shell is an application that provides system interaction to users.

> What I see is a void. There is no good language for system tasks (and no good shell). What's near this void is outdated shells on one hand and generic (non-DSL) programming languages on the other. Both are being (ab)used for system tasks.

Aside from the, in my opinion, abhorrent word "outdated" (why are old things considered bad just because of their age?), the comment about there being "no good shell" is something I disagree with very much. Personally I'm really fond of zsh and its manual pages are a treasure trove. But, lest this digress into a flamewar about shells or into a non-productive discussion about preferences, the point I would rather make is that the author provides a different thing than, as it seems to me, qualifies as a shell.

For example, the open issue mentioned in the README is:

Open issue: how to deal with a command that requires interaction.

As a Linux system administrator I am happy with the tools I have, and initiatives such as this seem to digress into the realm of the programmer. Sysadmins and programmers (a.k.a. developers - though I'd consider myself a developer too but not a programmer) tend to have very different perspectives about how to get an application onto the environment on which it runs, within the greater system of servers and networks.

In that sense, Docker and such mostly seem to get a preferential treatment from programmers, while sysadmins (again, as it seems to me) tend to dislike these kinds of abstractions. And I often get the impression that developers haven't got as much appreciation for sysadmins and what they do, as vice versa, but this could be false, or even more likely is that this is true for some and false for other cases. OMMV.

NGS might be a very useful project, I'm not at all negative about the project itself. It just seems more useful to programmers than to people like me who enjoy nothing more than to interact with their command line interfaces a.k.a. shells.

3 comments

I'm suprised you can't think of problems you currently have with shells. Here is a few of mine:

* Once I've started a program, and easy way of sending it to the background if it is taking a while, which sends it's output to some buffer I can refer to later, rather than continuing to spew it all over the screen.

* While we are at it, stop spewing the output of multiple programs over the screen, under any circumstances.

* Have some simple, easy to follow rules which let me work on files that have spaces in their names, without having to remember the various commands with various special cases (like -print0).

Thanks to tmux, I don't have a problem with multiple interactive commands and their outputs. If I need to do something new, I open another shell on a new pane. Not that other solutions aren't welcome, but this works for me.

If I don't want output at all, the &>/dev/null output redirection works, or file descriptor redirection, for which zsh has useful methods.

Spaces in filenames are easily solved by quoting filenames or variables. Again, zsh provides a myriad of ways to make this a trivial issue.

My main point was to argue what qualifies as to being called 'shell'.

One of the problems tmux and friends don't solve that a "smarter" underlying system might add is the ability to make the choice to detach a process or redirect its output after it's already begun running.

For example, I specifically have had on many occasions started something and then later wished I'd previously started screen. While, "gain the knowledge to better configure your environment to start" is a valid response, equally valid is a desire for a more flexible default environment in general.

"Detach during running" is a problem solved from the beginning of shells: just suspend a foreground command with C-z and type `bg` to wake it up in the background.

Output redirection seems to be a valid point, though.

I'd personally like a way to redirect the output of a running process (either `bg`d or `disown`ed) to a log file. The only way I've come across are horrible hacks using gdb[1] or strace.

This should be easier. Anyone know of any better ways? I'd like to be able to do something like `proclog <pid> <stdout output file> <stderr output file>`.

[1]: http://stackoverflow.com/questions/593724/redirect-stderr-st...

There's this: http://www.isi.edu/~yuri/dupx/dupx_man.html

Still uses gdb under the covers, but presents a front end close to what you are asking for.

For the first two issues, I use tmux. If something is long-running, I open a new shell to continue working. If I want to run multiple related commands, I can open many shells and have tmux send my keystrokes to all of them.
issue 1) sounds like you miss nohup, sreen or tmux in front of that long running program.

issue 2) usually I don't have one terminal session with multiple programs doing output at the same time, this solves this issue.

Just use a new xterm, a new terminal tab, a new screen tab for programs that are going to produce output and stay running.

issue 3) I think you refer to files with other special characters, because spaces on filenames do not need -print0 at all, simply proper quoting in the code will do.

Regarding issue 3, there is a lot of caveats when coding shell; even file names starting with a dash (-) which are interpreted as options by tools external to the shell (which fortunately support a double dash (--) to stop processing parameters).

This is the canonical writeup about argument injection vulnerabilities:

http://www.defensecode.com/public/DefenseCode_Unix_WildCards...

The point of issue 1 is that sometimes you don't know that the program will run for a long time. So a way to send a program into the background while it is already running, would be nice.
'Ctrl + z', 'bg' and 'fg' are for that.
Except, now you are back to my original problem -- the output of the program will continue to spew all over my terminal.
Well, if you work always in tmux/screen (a recommended practice for operations, that I did import to my daily shell activity) you don't need job control.

When there is a "surprisingly slow" command, then just press the shortcut for a new screen session.

Will get alerted in the status bar when the slow command finishes.

Output of each command will be in it's own screen session (not mixed).

That Ctrl + z response was no for issue1, but for the wishes of the second sentence of @hibbelig.

What you are asking for, "post-redirection" (a term I just coined) is not an easy task. Redirection is, but that's set up prior to the program run (warning: pseudocode ahead):

    child = fork()
    if child == 0 then
      stdout = open("output","w")
      stderr = open("error","w")
      dup2(stdout,FILENO_STDOUT)
      dup2(stderr,FILENO_STDERR)
      Close(stdout)
      Close(stderr)
      Execve("someprogram",arglist,envlist)
    End
Standard Unix stuff. But doing that after the program is running isn't easy. The only way I know of is to send the program SIGSTOP (stops execution of the program---said signal can't be caught), and using ptrace(), inject code into the process to open the output file and call dup2() to get the redirection going, calling said code, then resuming the program.

I suppose one could script gdb (or whatever Unix debugger exists on the suystem) to do such a thing, but the fact that no one has really done this might mean something.

Those can all be seen as tweaks to existing shells. With regards to...

"* Have some simple, easy to follow rules which let me work on files that have spaces in their names, without having to remember the various commands with various special cases (like -print0)."

I'm not sure I understand what's hard about files with spaces in their names. I'd say it's easy enough to work with such filepaths by using tab autocomplete when using the shell interactively, and quote marks when writing shell scripts. Can you give an example of where these approaches wouldn't work?

When you pipe the output of one command into another, e.g 'ls | wc' (obviously a dumb example), the second command will split the filenames on spaces and so will not run properly.

The workarounds for this all involve nasty extra parameters for different commands (e.g. the -print0 example)

ls is not bash wc is not bash

And that is a discouraged way to count files in shell script.

Still, simply adding -l to ls, could handle spaces correctly (the files count)

I insist, spaces are not your enemy, there are much more weird file names for a shell. Shell can handle spaces if used properly.

You miss my point. Of course, for every example I give, it's possible to build a workaround to handle the spaces. My point is, it's the very fact that you need a workaround that makes it so irritating.

'command1 | command2' just works in most circumstances, so it's frustrating that it falls apart when a filename with a space appears.

And it technically is a shell issue, insomuch as the shell is dividing up the ARGV for each program. The shell is perhaps not to blame, because it can't tell the difference between a filename that has a space in it, and ordinary output that just so happens to correspond with a filename. In other words, it's hard to see what a shell could do to make things better. But the problem still exists.

wc is not a builtin.

In that example we're not in front of a bash word splitting issue.

I agree with you that shell scripting has caveats one need to learn. As does Perl, C, PHP, Ruby, Node, Go, Java and what not.

I don't feel a big change is needed to handle spaces in shell scripts, my scripts handle them and I enjoy writing them. Maybe you know of minor tweaks for bash,zsh or any common shell which could be useful in general purpose of files with spaces in the name? don't hesitate to open them a bug, maybe we even get a fix.

But don't send them this example, and insist on it, because the conversation is over:

    $ touch a_file
    $ ls | wc
          1       1       7
    $ rm a_file
    $ touch "a file"
    $ ls | wc
          1       2       7
Equivalent input, with/without spaces and expected output.

The 2 is a word count, and we did pass two words, I don't expect a 1 there, _that_ could be a bug.

That there are worse things that exist is no reason not to pluck the low hanging fruit. I see this attitude on HN a lot. Spaces are probably the 80 in the 80/20 rule here. Why not address them?
Please give a single example in shell about spaces, that has not been already addressed.

From where do your get that rule?

Not sure on why this comment got down-voted.

If it's because I did not explain how to do that, there is howto do it:

    http://mywiki.wooledge.org/BashFAQ/004
If it's because the comment on the given example...

    $ touch file1
    $ ls -l | wc -l
    1
    $ touch "file 2"
    $ ls -l | wc -l
    2
... (?)

If we were talking about "new lines in file names", or "dashes at the beginning of file names", or code injection through file names, then we could be talking of more complex solutions.

But the space issues in shell are simple, and have known solutions. If you're a daily user or you're not at learning stage, spaces don't turn to be a issue.

I'm guessing it was down-voted because you keep missing the point. Yes, there are work-arounds for this scenario, but the overhead in remembering the work-arounds is the problem. He's not saying you can't do it, he's saying the problem is that you have to change your setup for edge-cases, which are actually fairly common.
But, I need to remember to do that.

How about (for example):

    $ for i in $(ls | grep 'cheese\|fish' | head -n 5) ...
I'm sure there is a way to make this work correctly (take 5 filenames containing either cheese or fish), but I'd need to put more thought into making it work correctly.
wc, in its basic form, is made for counting words. A filename in your case is not a word. I don't see the problem here. Use wc in line mode and the "problem" is solved.

It also has nothing to do with the shell, nor does the general case of pipes you present below. Your shell redirects the output from ls to the input of wc. If you don't like the simple approach that tools consume and produce arbitrary text in a manner it sees fit for its purpose,, maybe it's your operating system that you have a beef with.

Just use tmux. It'll take a day to figure out, and then all your problems go away. Well, save the spaces, that's never going to happen.
> all your problems go away. Well, save the spaces, that's never going to happen.

Spaces in filenames are fine. The only strange thing is that, as it turns out, shells have this hidden easter-egg/anti-feature where you can actually leave out the quotes around filenames under certain, special edge-case scenarios. One of those is when the filename contains no ampersands, quotation marks, asterisks, dollar-signs, parentheses, backslashes, newlines, or, you guessed it, spaces! In fact, this special "no quote mode" also contains another special, embedded mode where you can still use those characters, but put backslashes before them! Since this layering of tricks leads to funky, confusing-looking commands, it's obviously much better to just stick with the regular mode of quoting everything.

Of course, the above is quite tongue-in-cheek, but its the mental-mode I specifically try to adopt: "occasionally, you might get away with leaving out the quotes"; compared to the seemingly more common "you need to add quotes in these cases".

Still, this doesn't eliminate the problem of single-quotes in filenames never going away! Whilst it only requires one character code to be escaped, it's still accomplished in a pretty funky way: "'" becomes "'\''"; we first close the string, then use a backslash to write a literal "'", then we start a new string ;)

You could use a shell that magically handles all the escaping for you either while typing/pasting for some programs (curl, grep etc) when not in quotes and tab completes with a selector so you don't have to think about spaces, special chars, etc:

http://paste.click/VfUUWv

By and large I agree. As a programmer, I generally feel like the sysadmins which I work with "hide" how they do things and aren't transparent enough about their role for me to know why I should respect them. I've seen some do amazing things and then I recognize the difficulty but I don't feel their is enough collaboration between the two sides
>Open issue: how to deal with a command that requires interaction.

Yet this problem is solved very simply in bash and other shells by simply allowing you to explicitly tell it when to run a command in the background and when not to using the & command.