I've found out about patches (and updates) for an x86 sh binary in 2007 to support sh DTrace provider.
However I can't find any probes on OS X. I'm checking by:
$ sudo dtrace -l | grep command-entry
See: /bin/sh DTrace Provider at Oracle site (same article on blog)
Maybe because my sh is the same as GNU bash?
$ /bin/sh --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin15)
Where these probes were implemented, how I can find them or how I can activate them?
Were there only implemented on Solaris?
I never added it to the bourne shell in a public Solaris (although I got the PSARC approval for it) as while testing I found some major performance hits in the way that the bourne shell forks. In order to address this I'd have to migrate it to using posix_spawn(). Given that we were moving away from using this shell in Solaris 11, this was an amount of work that would have been pretty fruitless. I haven't given up on going to other shells, but it's not one of my immediate priorities.
Moving the probes to another shell should be pretty painless, except for deciding what to return as the prior value in "variable-assign", when we have compound variables.
The patches you refer to were specific to the bourne shell on Solaris, and as far as I know nothing like it has ever been ported to other shells.
In the illumos (née OpenSolaris) commit history, we can see that /bin/sh was changed to be a symlink to ksh93 in commit ead1f93 on March 2, 2010. Considering that Alan's blog post is dated 2007, this wasn't included in Solaris 10, at least not initially since Solaris 10 was released in 2005. It may be in one of the updates post 2007 but I sort of doubt it. From the existing code, I can't even find what provided /bin/sh before the switch to ksh, which might mean it was one of the closed bits.
Either way, it was never part of any illumos release and I don't see any references to dtrace probes for command-entry in the illumos commit history. Unless Alan or somebody else close to the matter can speak up, it's probably lost to time.
In summary, as near as I can tell these patches were never included in any released product from Sun or otherwise. It will almost certainly have to be reimplemented from scratch on any existing open source shell.
Related
I am trying to get tab completion on the second atom of a command.
I.e. man do<tab complete>
In bash this can be done with complete -cf <command> but I am not sure if this is possible in ksh. Any Ideas?
It depends on which ksh flavour you are using.
In AT&T ksh88 as well as pdksh and derivatives (mksh, NetBSD ksh, OpenBSD ksh / oksh), this is not possible (asides from really weird hacks. They (I can say that for guaranteed for mksh as I am its developer) complete the second (and follow-up, except after a closing parenthesis )) word of a command consistently as cwd-relative pathname (“file” simplified).
AT&T ksh93 in the last version from AT&T 93u+20120801 does not have programmable tab completion; however, the new development under situ from Red Hat introduced it, as indicated in the manpage. You will not likely find this in any stable distro yet, however, they have recently issued their first stable post-fork release.
I typically put a shebang for bash at the top of my shell scripts, e.g.:
#!/usr/bin/bash
However I see many other variants of this, like #!/bin/bash or #!/usr/local/bin/bash etc.
It seems to me these different conventions would result in compatibility or portability issues. If my bash is at another location than someone else's, my script won't work on their machine and vice versa.
If a shell interpreter like bash is apparently not always at the same location, isn't it plain WRONG to explicitly use a hardcoded path in a script?
I understood you can use a somewhat more flexible or less system-dependent approach like this:
#!/usr/bin/env bash
Which results in the (or a?) local version of bash, wherever that may be installed.
Does the latter variant always work? Or is there a better approach that has the highest chance of referring to any system's bash regardless of where it's installed?
I would recommend either "#!/bin/bash" or "#!/usr/bin/bash". On a modern Linux distro, bash should be installed in both places.
Apparently, that isn't true for OpenBSD ... which uses ksh as the default shell. But on an OpenBSD system, you are liable to find that bash isn't installed at all. It is apparently an optional package, and the admin may have not installed it.
So, if you want to maximize portability, use "/bin/sh" and restrict yourself to standard POSIX shell syntax and commands. "/bin/sh" is typically a link to bash or ksh, and runs in POSIX compliant mode.
Other variations:
"#!/usr/local/bin/bash" typically won't work on Linux. If it does, it may give you a locally built / modified version of bash.
"#!/usr/bin/env bash" should work, with a couple of caveats:
This will give you whatever version of bash is first on the user's command search path (i.e. $PATH).
It is conceivable that the path to env may be different, or that it may not exist. (The env command wasn't in the first version of the POSIX specs.)
Why it is recommended to use /usr/bin/env python as opposed to /usr/bin/python.
This was inspired from reading the responses here:
What do I use on linux to make a python program executable
I think both would do exactly the same thing, but the answer that mentions both equally has 2 votes, rather than 88 votes for the answer that says to use env. People seem to really agree with using env, but don't explain why. Does env help you find any executable named "python", rather than just the one in a specific path which the user could have customized?
I'm really interested to know the various advantages and use cases for using env, and man env didn't explain it. man env only says that you can use env to set environment variables before running, NAME=VALUE, but we aren't doing that in the linked example.
I feel the community clearly is recommending to use env, but my own research has not hinted at a reason, so if you have ideas why it's good or good style to do so, please answer.
Using #!/usr/bin/env python ensures that the first Python interpreter in the currently-defined PATH is used, honoring any user overrides (which, for Python, includes virtualenvs and the like).
This is particularly important for environments such as MacOS, where OS-vendor packages are often out-of-date (for instance, /bin/bash is 3.2 -- a release series from 2006 -- whereas if the user has MacPorts or Homebrew, /opt/local/bin/bash or /usr/local/bin/bash may be a modern 4.x; thus, #!/usr/bin/env bash will gain the benefit of any updated bash interpreter a user has installed, whether system-wide or under their home directory, so long as the location of that interpreter is present in their PATH at runtime).
While looking at my friend's Makefile, I noticed that he used the install shell command. From what I can tell, the command allows you to install and chmod files with one fell swoop. The command came up in a subsequent conversation of ours, and he said he had heard that the command is considered somewhat archaic, and that developers should use cp, mv, chmod etc. for modern projects.
Strangely, this has been my only encounter with the command. This leads me to believe that the command has indeed been rejected and hence forgotten. Is this true? Is there some sort of security flaw with the program? From my possibly naive point of view, using a single command is always better than using many commands
I suspect the answer is that the install command is pretty much only used in scripts and makefiles (such as the automake makefiles that #Jack Kelly describes), and almost never interactively. Thus people rarely see it 'over someone's shoulder', and it doesn't lodge in their consciousness.
It is however, as you say, pretty much exactly the right tool for this job. The problem is that it's not a POSIX command, so it's wise not to use any terribly exotic options. The version of it used in automake makefiles is supplemented by a distributed shell script if the configure script hasn't convinced itself that the local version is sufficiently compatible.
See the autoconf manual's discussion of portable shell scripting, for some useful tips on this general topic.
Makefiles generated by automake still use it, as evidenced by the line (or similar):
checking for a BSD-compatible install... /usr/bin/install -c
in the output of configure.
As the title suggests — can I be reasonably sure that mktemp will exist on any unix-y operating system I'm likely to encounter?
POSIX does not seem to specify mktemp(1).
It looks like most modern systems have it, but the available functionality and the semantics of the options vary between implementations (so particular invocations may not be portable):
mktemp(1) from OpenBSD — mktemp(1) originated in OpenBSD 2.1
mktemp(1) from FreeBSD
mktemp(1) from Mac OS X — almost always the same as from FreeBSD
mktemp(1) from Todd C. Miller of sudo fame
mktemp(1) from Solaris
mktemp(1) from GNU coreutils
mktemp(1) from HP/UX — this one seems particularly divergent from most of the others listed here
So if you want a portable solution you may need to stick to functionality and options that mean the same thing on all of your platforms of interest.
A mktemp function (AKA mktemp(3)) first appeared in Unix V7 so it's likely to be everywhere. However, a mktemp command (aka mktemp(1)) first appeared, I believe, on OpenBSD 2.1, so if you have to deal with truly antediluvian Unix systems you might have to worry -- unless you can distribute the very portable mktemp.org version (to fix the potential lack of this utility on some customer's antediluvian system). How likely you are to encounter antediluvian system is nigh impossible for us to guess, of course -- e.g., in HP-UX, mktemp(1) has been around for at least 8 years (even most enterprises probably have updated their Unix OS's within that time frame), in Xenix I believe it appeared in 3.0 (in 1992), etc, etc.
FYI, mktemp appears to NOT be included with Solaris 9 (released 2002/2003) - just ran across this today:
$ uname -a
SunOS dcmnapp02 5.9 Generic_122300-47 sun4u sparc SUNW,Sun-Fire-V440
$ mktemp
bash: mktemp: command not found
$ man mktemp
bash-2.05$ man mktemp
Reformatting page. Please Wait... done
Standard C Library Functions mktemp(3C)
NAME
mktemp - make a unique file name
SYNOPSIS
#include
char *mktemp(char *template);
On Solaris 9 it's in package SMCmktemp, see http://sunfreeware.com/indexsparc9.html:
uname -s
SunOS
uname -r
5.9
/usr/sbin/pkgchk -l -p /usr/local/bin/mktemp
Pathname: /usr/local/bin/mktemp
Type: regular file
Expected mode: 0555
Expected owner: bin
Expected group: bin
Expected file size (bytes): 8884
Expected sum(1) of contents: 6493
Expected last modification: Nov 05 08:48:17 2002
Referenced by the following packages:
SMCmktemp
Current status: installed