ANNOUNCE: HsUnix 1.0.1 - Haskell for Unix Shell Scripting
I'm pleased to announce the first release of the HsUnix library. It enables you to do things easily in Haskell which are typically done by the shell. Thus Haskell can be used to write shell scripts. Features -------- Command Line Arguments Parser HsUnix has facilities for managing command line arguments, which are (hopefully) easier to use than the GHC library GetOpt. Command line arguments are described in lists of properties. HsUnix builds on top of GetOpt, but hides it completely. Command line arguments handling has been added because GetOpt was found to be too cumbersome. Shell Like Commands HsUnix has a growing list of front end functions for shell like programming, such as chmod or mkdir. They wrap calls to external programs, system calls or standard Haskell functions. Analyzing Paths Dealing with paths is not as trivial as it sounds. Take, for example ../for///./../bar/. HsUnix has taken care of it thoroughly and provides functions such as splitting a path into (real) path components, or syntactically normalising paths. Dealing with Processes and Calling External Programs There are corresponding functions in the GHC Posix library, but the ones here are simpler. Redirecting Input and Output HsUnix defines operators like ->- and ->>- which work just like redirection operators in shells. Building Pipes Reading the output of an external program, or piping the output of one program into the input of another, is almost as easy as in shells. HsUnix provides corresponding operators. Error Handling Error handling is one thing which is done much more thoroughly in HsUnix than in shells. Failed programs won't be silently ignored. Dynamic exceptions are used for error handling. Non zero exit codes are thrown as exceptions. Quoting of Strings and Building Commands for Shells Taking care of shell metacharacters usually isn't done right. HsUnix provides functions for doing it safely. Homepage -------- http://www.volker-wysk.de/hsunix -- Volker Wysk <post@volker-wysk.de> http://www.volker-wysk.de
"VW" == Volker Wysk <post@volker-wysk.de> writes:
VW> I'm pleased to announce the first release of the VW> HsUnix library. It enables you to do things easily VW> in Haskell which are typically done by the VW> shell. Thus Haskell can be used to write shell VW> scripts. Thanks, sounds great. :) Though the tarball I just downloaded only seems to contain HsUnixArgs.hs. Perhaps something went wrong with it? Jens
"VW" == Volker Wysk <post@volker-wysk.de> writes:
VW> I'm pleased to announce the first release of the VW> HsUnix library. It enables you to do things easily VW> in Haskell which are typically done by the VW> shell. Thus Haskell can be used to write shell VW> scripts.
Thanks, sounds great. :) Though the tarball I just downloaded only seems to contain HsUnixArgs.hs. Perhaps something went wrong with it?
The tarball was corrupted. I've reuploaded it. It should be fine now. I've gut idea how this could happen. bye, Volker
On Sun, Feb 08, 2004 at 09:36:16PM +0100, Volker Wysk wrote:
Features --------
Command Line Arguments Parser HsUnix has facilities for managing command line arguments, which are (hopefully) easier to use than the GHC library GetOpt. Command line arguments are described in lists of properties. HsUnix builds on top of GetOpt, but hides it completely. Command line arguments handling has been added because GetOpt was found to be too cumbersome.
I found GetOpt to be convenient when used properly. I would be interested to hear your comment on my article: http://tinyurl.com/23ya4
Error Handling Error handling is one thing which is done much more thoroughly in HsUnix than in shells. Failed programs won't be silently ignored. Dynamic exceptions are used for error handling. Non zero exit codes are thrown as exceptions.
Most sh derivaties have -e set option, which causes the shell to (taken from FreeBSD sh man page): -e errexit Exit immediately if any untested command fails in non-interactive mode. The exit status of a command is considered to be explic- itly tested if the command is used to control an if, elif, while, or until; or if the command is the left hand operand of an ``&&'' or ``||'' operator. I use it almost always in my shell scripts. Best regards, Tom -- .signature: Too many levels of symbolic links
On Mon, Feb 09, 2004 at 12:49:28PM +0100, Tomasz Zielonka wrote:
On Sun, Feb 08, 2004 at 09:36:16PM +0100, Volker Wysk wrote:
Error Handling Error handling is one thing which is done much more thoroughly in HsUnix than in shells. Failed programs won't be silently ignored. Dynamic exceptions are used for error handling. Non zero exit codes are thrown as exceptions.
Most sh derivaties have -e set option, which causes the shell to (taken from FreeBSD sh man page):
-e errexit Exit immediately if any untested command fails in non-interactive mode.
It doesn't work. #!/bin/sh -e cat nosuchfile | echo hello This script will exit with status 0 (success). If you think about how traditional unix shells are implemented, you will see that they can't get this right. (Which proves the non-existence of reliable non-trivial shell scripts!) I have my own half-finished shell-in-Haskell that handles this. I would be interested to know whether HsUnix does. Andrew
On Mon, Feb 09, 2004 at 11:07:39AM -0500, Andrew Pimlott wrote:
-e errexit Exit immediately if any untested command fails in non-interactive mode.
It doesn't work.
Well, it works as much as it can... better something than nothing.
#!/bin/sh -e cat nosuchfile | echo hello
Yes, I forgot about this issue.
I have my own half-finished shell-in-Haskell that handles this. I would be interested to know whether HsUnix does.
So would I.
Andrew
Best regards, Tomasz -- .signature: Too many levels of symbolic links
On Mon, Feb 09, 2004 at 12:49:28PM +0100, Tomasz Zielonka wrote: #!/bin/sh -e cat nosuchfile | echo hello
This script will exit with status 0 (success). If you think about how traditional unix shells are implemented, you will see that they can't get this right. (Which proves the non-existence of reliable non-trivial shell scripts!)
I have my own half-finished shell-in-Haskell that handles this. I would be interested to know whether HsUnix does.
The equivalent HsUnix script looks like this: import HsUnix main = mainwrapper $ call (execp "cat" ["nosuchfile"] -|- execp "echo" ["hello"]) This happens to work right. The error is reported via a dynamic exception: ~/src/hsunix/build $ ./test2 cat: nosuchfilehello : No such file or directory Process error. process status = Exited (ExitFailure 1) However, when using pipes, the exitcode of only one of the involved processes can be monitored. The other ones will be silently ignored. If the second process would fail in the above pipe, rather than the first one, no error would be reported. In this case, you could use "-|=" instead of "-|-". Then the second process would be monitored. Bye, Volker -- Volker Wysk <post@volker-wysk.de> http://www.volker-wysk.de
On Mon, Feb 09, 2004 at 07:16:09PM +0100, Volker Wysk wrote:
main = mainwrapper $ call (execp "cat" ["nosuchfile"] -|- execp "echo" ["hello"])
This happens to work right. The error is reported via a dynamic exception:
~/src/hsunix/build $ ./test2 cat: nosuchfilehello : No such file or directory Process error. process status = Exited (ExitFailure 1)
However, when using pipes, the exitcode of only one of the involved processes can be monitored.
Let me give my frank opinion that, even though it's how shell scripts have always worked, this should be considered broken. It is rather a pain to fix, as you can't implement it in the usual straightforward way. You have to fork all subprocesses from the main process, and do extra work to share the pipes. If you don't want to use filehandles extravagantly, you have to do additional work. I essentially wrote a mini-OS layer that wraps all fork, pipe, and open calls, and tries (in a fairly dumb but usually effective way) to allocate filehandles efficiently. I can share if you'd like. (I found this exercise gave great insight into the "worse is better" philosophy.) If you don't change this behavior, at least document it prominently as a robustness sink! :-) Andrew
On Mon, 9 Feb 2004, Andrew Pimlott wrote:
However, when using pipes, the exitcode of only one of the involved processes can be monitored.
Let me give my frank opinion that, even though it's how shell scripts have always worked, this should be considered broken.
Well, HsUnix is somewhat better, since one process can be monitored.
It is rather a pain to fix, as you can't implement it in the usual straightforward way. You have to fork all subprocesses from the main process, and do extra work to share the pipes. If you don't want to use filehandles extravagantly, you have to do additional work. I essentially wrote a mini-OS layer that wraps all fork, pipe, and open calls, and tries (in a fairly dumb but usually effective way) to allocate filehandles efficiently. I can share if you'd like. (I found this exercise gave great insight into the "worse is better" philosophy.)
I wonder if this could be incorporated in hsunix. I'd like to take a look at your implementation.
If you don't change this behavior, at least document it prominently as a robustness sink! :-)
I've added it to the documentation. Regards, Volker
wouldn't it be nicer to have - mainwrapper and call combined - helper fucntions defined for execp "cat" etc i haven't downloaded your package, but the syntax as it is looks very verbose. i know it's a small point, but shells have to support a compact syntax (or is the idea only to support "shell scripts" and not provide a shell? - i was assuming you'd start ghci in a window and load this module automatically when you open an xterm...) andrew Volker Wysk said:
The equivalent HsUnix script looks like this:
import HsUnix
main = mainwrapper $ call (execp "cat" ["nosuchfile"] -|- execp "echo" ["hello"])
-- personal web site: http://www.acooke.org/andrew personal mail list: http://www.acooke.org/andrew/compute.html
Hi
wouldn't it be nicer to have - mainwrapper and call combined
mainwrapper catches all the exceptions. This may not be what you want. You end up ignoring errors again (except for the message).
- helper fucntions defined for execp "cat" etc
Yes, this would be easy.
i haven't downloaded your package, but the syntax as it is looks very verbose. i know it's a small point, but shells have to support a compact syntax (or is the idea only to support "shell scripts" and not provide a shell? - i was assuming you'd start ghci in a window and load this module automatically when you open an xterm...)
HsUnix is meant for shell scripts only. I don't know if it's possible to use it interactively in ghci. I don't think it's such a good idea to build a Haskell based interactive shell, anyway. Volker
I found GetOpt to be convenient when used properly. I would be interested to hear your comment on my article: http://tinyurl.com/23ya4
Your technique is quite elegant. It does essentially the same as HsUnix, when it is used the way I use it in my scripts. You can find examples in the user manual, in the src/manual/exampels/src directory. Regards, Volker
participants (5)
-
andrew cooke -
Andrew Pimlott -
Jens Petersen -
Tomasz Zielonka -
Volker Wysk