Is setsid command missing on OS X? - macos

I mean I can't use it in bash, is it not available on OS X, or is it just missing on my Mac?
It's not a PATH variable issue, because I searched with find command, and there's no file named setsid on my Mac at all.
If it's missing on OS X, is there any alternative to it?
Or if it's the case that I somehow deleted it accidentally, where can I find a copy of it?

use Brew:
brew install util-linux

Yes. /usr/bin/setsid is missing on Mac OS/X.
The OS interface is available, so based on the chapter 2 man page there may be some hope for porting the Linux source to Darwin.

While macOS does not come with a setsid command, it does come with scripting languages which support calling the setsid C function, such as Perl and Python. So, if you don't want to (or for some reason can't) install a setsid command via Homebrew (or MacPorts or whatever), another option is to write your own in a scripting language. As an example, try this Perl script (which I based off this with some minor changes):
#!/usr/bin/perl -w
use strict;
use POSIX qw(setsid);
fork() && exit(0);
setsid() or die "setsid failed: $!";
exec #ARGV;
If you don't like Perl, Python's os module has a setsid function too.
A simple demo, which relies on the fact that /dev/tty is an alias of your controlling terminal if you have one, but reads/writes to it fail with an IO error if you don't:
$ bash -c 'echo I have a controlling terminal. > /dev/tty'
I have a controlling terminal.
$ ./setsid.pl bash -c 'echo I have a controlling terminal. > /dev/tty'
bash: /dev/tty: Device not configured
$
(Warning: With the release of macOS Catalina (10.15) in 2019, Apple deprecated the Perl, Python, Ruby and Tcl language runtimes shipped with macOS – they say new software should not use them, and they may be removed in a future macOS version – and Apple is not going to update their versions, which are becoming increasingly outdated. However, they are still there in Monterey, and while I haven't upgraded to Ventura yet, I haven't heard anything about their removal in that version either. One obviously shouldn't rely on them for any supported applications – if such software needs one of these runtimes, it should install its own copy of them. However, if it is just for a quick hacky script to easily test how some program behaves without a controlling terminal, using these OS-bundled runtimes is still fine.)

Related

Why date '+%s%N' not working on mac terminal?

I am working on bash scripts on both linux and mac.
I run this command on remote server with linux OS and it just work perfect.
CURRENT_TIME=$(date '+%s%N')
echo "$CURRENT_TIME"
However, when I run the same command on mac terminal, it shows this error:
1654778186N: value too great for base (error token is "1654778186N")
It look like mac terminal did not recognized the '%N'. What should I do to fix the issue on mac terminal?
%N is a GNU extension to the POSIX standard, as clarified in GNU's own documentation: https://www.gnu.org/software/coreutils/manual/html_node/Time-conversion-specifiers.html
The POSIX version of date, doesn't include %N: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/date.html
If I recall correctly, POSIX-certified systems (and macOS is certified) cannot add custom extensions to POSIX tools to guarantee portability across systems.

How to use default path for ActivePerl 5.20 Mac OS X (/usr/bin/perl) instead of /usr/local/ActivePerl...?

I have installed ActivePerl 5.20.2 today on Mac OS X 10.9.5
Checking the version of perl in Terminal (perl -v) I see 5.20.2
So everything seems to be ok. But..
When I start my CGI scripts the script is running under built in perl (which is 5.16) (if using #!/usr/bin/perl).
If I use #!/usr/local/ActivePerl5.20.2/bin/perl then it runs under 5.20.2 that is required.
The question is: is it somehow possible to change the directory for using in my scripts from #!/usr/local/ActivePerl5.20.2/bin/perl to simple and familiar #!/usr/bin/perl keeping running under ActivePerl instead of built in.
I need to override the system's default version with the new ActivePerl.
I would be appreciated for your detailed answers (with name of files and directories where they are located) if ones are to be changed to implement salvation.
Thanks!
The question is: is it somehow possible to change the directory for using in my scripts from #!/usr/local/ActivePerl5.20.2/bin/perl to simple and familiar #!/usr/bin/perl keeping running under ActivePerl instead of built in.
Don't even try. That way lies damnation, not salvation. The ability to specify the specific interpreter that will handle your scripts is an important feature.
Instead, package your CGI script as a simple CPAN module. Then, install it using the familiar
$ /usr/local/ActivePerl5.20.2/bin/perl Makefile.PL
$ make install
routine. The shebang line will be automatically adjusted to reflect the perl that was used to build and install your package.
First, instead of specifying a particular path to your Perl interpreter in your script:
#! /usr/local/ActivePerl5.20.2/bin/perl
or
#! /usr/bin/perl
Specify this:
#! /usr/bin/env perl
This will find the first executable Perl interpreter in your $PATH and then use that to execute your Perl script. This way, instead of having to change your program, you only have to change the $PATH variable.
Next time, take a look at PerlBrew for installing a different version of Perl. PerlBrew will allow you to install multiple versions of Perl all under user control, and let you select which version of Perl you'd like to use.
I also recommend to put /usr/local/bin as the first entry in your $PATH. Then, link the executables you want to run to that directory. You can use something like this to create your links:
for file in $/usr/local/ActivePerl5.20.2/bin/*
do
basename=$(basename $file)
ln -s "$file" "/usr/local/bin/$basename"
done
This way, all programs you want to execute are in the same directory which makes setting $PATH so much easier. I even put /usr/local/bin in before /usr/bin and /bin because I want to be able to override the system's default version.

How can I make bash deal with long param using "getopt" command in mac?

I want to make my bash script deal with long parameters. I found getopt, but it isn't supported in OS X. Can anyone tell me why getopt was implemented by BSD, but not GNU?
I tried building getopt in GNU C lib, but it failed for my poor skills with Linux.
Did anyone do this work?
There is a brew bottle for getopt.
Just run brew install gnu-getopt.
You can either specify the path for it like
/usr/local/Cellar/gnu-getopt/1.1.6/bin/getopt
Or use brew link --force gnu-getopt so it will be linked in /usr/local/bin/
Just be aware that forcing linking might be corrupting your system (as it replaces the system getopt by the gnu one).
See maybe later answer suggesting to define FLAGS_GETOPT_CMD (though few comments state issues with it).
I recommend using Homebrew to install gnu-getopt and then adding $FLAGS_GETOPT_CMD to your ~/.bash_profile file to specify the cmd path for getopt, pointing at the homebrew location, like so:
brew install gnu-getopt
Then follow directions from brew to add to your local path:
sudo echo 'export PATH="/usr/local/opt/gnu-getopt/bin:$PATH"' >> ~/.bash_profile
Then you can add FLAGS_GETOPT_CMD:
sudo echo 'export FLAGS_GETOPT_CMD="$(brew --prefix gnu-getopt)/bin/getopt"' >> ~/.bash_profile
Open a new terminal, or run . ~/.bash_profile in existing terminal to load changes
Run echo $FLAGS_GETOPT_CMD to confirm it was actually set in your console
It's generally a better idea to use getopts instead, and stick with short options. You can see getopts in action in this StackOverflow Q&A. Short options are more standard throughout OSX command line tools, and consistency is a good thing.
Also, getopts is built in to bash, so it's definitely available in OSX, as well as every other platform that can run bash.
Note that there is a getopt is also available in OSX. From Terminal, type man getopt to see its documentation. It doesn't support long options. This is a good reason not to use long options when you're writing tools to run on OSX.
If you want to do this anyway, you can install getopt from macports. Alternately, if you want better portability, you can roll your own long argument handling.
Post some code, and we'll help debug it.

Mac OS X equivalent of Linux flock(1) command

Is there a flock command on Mac OS X that manages file lock?
http://linux.die.net/man/1/flock
There is a cross-platform flock command here:
https://github.com/discoteq/flock
I have tested it and it works well on OSX as a drop-in replacement for the util-linux flock.
Perl one-liner:
perl -MFcntl=:flock -e '$|=1; $f=shift; print("starting\n"); open(FH,$f) || die($!); flock(FH,LOCK_EX); print("got lock\n"); system(join(" ",#ARGV)); print("unlocking\n"); flock(FH,LOCK_UN); ' /tmp/longrunning.sh /tmp/longrunning.sh
As a script:
#!/usr/bin/perl
# emulate linux flock command line utility
#
use warnings;
use strict;
use Fcntl qw(:flock);
# line buffer
$|=1;
my $file = shift;
my $cmd = join(" ",#ARGV);
if(!$file || !$cmd) {
die("usage: $0 <file> <command> [ <command args>... ]\n");
}
print("atempting to lock file: $file\n");
open(FH,$file) || die($!);
flock(FH,LOCK_EX) || die($!);
print("got lock\n");
print("running command: $cmd\n");
system($cmd);
print("unlocking file: $file\n");
flock(FH,LOCK_UN);
I don't believe that the flock command exists on OS X, but it does exist on BSD which should make it reasonably easy to port to OS X.
The closest that is available is the shlock command (man page), but it isn't as robust or secure as flock.
Your best bet may be to look at porting either the Linux or BSD version of flock to OS X.
macOS does not ship with a flock command, no, but you can install one via Homebrew (brew install flock). Which is probably the way to go if you need a shell script that can share a lockable resource with programs that use the flock system call to manage access to that resource.
If you are just trying to synchronize access to something and don't require compatibility with things already using flock, you could alternatively install procmail and use lockfile instead.
Just for completeness sake, you can compile flock(2) for OSX with some minor changes, i have not run any tests, but basic functionality works.
You can get the source from ftp://ftp.kernel.org//pub/linux/utils/util-linux. You then need to replace some calls to string functions not available on OSX, and you're good to go.
Here: https://gist.github.com/Ahti/4962822 is my modified flock.c of version 2.22.1, you still need the other sources for headers though.
You can install flock via conda, for example:
conda create --name flock flock
or
conda install flock
To install conda, see here.
Are you looking for flock the command line utility or flock the feature?
flock(1) is unavailable on OS X. flock(2) (the C function for file locking), however is.
Writing a simple command line flock(1) utility using flock(2) should be trivial.
You cannot write a shell-level flock(1) command for use in shell programming because of how file locking working. The lock is on the descriptor, not on the inode or directory entry.
Therefore, if you implement a shell command that flocks something, as soon as the locking command exits and the shell script moves on to the next command, the descriptor that held the lock disappears and so there is no lock retained.
The only way to implement this would be as a shell builtin. Alternately, you have to rewrite in a programming language that actually supports flock(2) directly, such as Perl.

emacs on OS X 10.6

I am a new iMac user. I have extensive experience with Linux on a PC. I downloaded latest version of emacs to the Applications folder. I want to invoke emacs from the command line. However, the default path for emacs is /usr/bin/emacs. what is the best practice for adding the new emacs to the path? I am tempted to create a ~/bin directory and a link to the new emacs and adding ~/bin to the beginning of my path. This is how we did things in our software development environment on linux PC's
Best way is to use Homebrew and use
brew install emacs --cocoa
so you have a easy to update emacs installation. The Cocoa will make sure you have your mac keybinding working before emacs. Make the binary run at startup as a daemon (because it starts up not very fast), for instance:
/usr/local/Cellar/emacs/23.2/Emacs.app/Contents/MacOS/Emacs --daemon
And make an script to the emacsclient command and saved it to /bin/emacs file (don't forget to make it executable):
#!/bin/bash
exec /Applications/Emacs.app/Contents/MacOS/bin/emacsclient -n -c "$#"
so when you fire up at bash "emacs something.txt" the already running emacs daemon opens it instantly. You can also extend it to open Emacs if the daemon is not running!
I tested it on the latest emacs 23.2, some features are not present on early versions.
Assuming you were still in linux land, wouldn't the canonical place to put this be in /usr/local/bin (and add that to your path?) ... I'd stick with that, if you were to go that route, but this is how I have my emacs setup:
I've downloaded the latest plain/vanilla Emacs from emacsforosx.com
I've made an emacs alias that I use to fire up a terminal-based version of emacs when I don't want (or can't) run the GUI version, like so:
alias emacs='/Applications/Emacs.app/Contents/MacOS/Emacs -nw'
If you want to fire up the GUI version of Emacs from the terminal, you can just type the following (which, AFAIK, is a mac-ism, so you wouldn't have known that coming from linux):
$ open -a Emacs
There's a slew of information about emacs on OS X at the emacs wiki.
~/bin or /usr/local/bin will work fine, as will manipulating your PATH.
Assuming you're using Emacs.app, simplest thing to do is to use open -a /Applications/Emacs.app "$#". open is the command line equivalent of double-clicking on something in Finder. Put that into a shell script, stick it into your PATH and go.
Installing emacs-app via MacPorts is probably the simplest way to get and maintain a Cocoa emacs.
You may wish to look into Aquamacs which is a further refinement of emacs for OS X. The emacs wiki page on Aquamacs is very helpful. It also has an option to add a little aquamacs script to your PATH that will open a file in the aquamacs GUI.
I create a shell script named emacs in my ~/bin directory containing:
open -a Emacs "$#"
Obviously, ~/bin needs to be before /usr/bin in my PATH which I set in ~/.profile so that it shadows the preinstalled emacs binary.
I also create a symlink via ln -s /Applications/Emacs.app/Contents/MacOS/bin/emacsclient ~/bin/emacsclient so that this also shadows the preinstalled emacsclient binary.
For additional connivence, I create an alias ec='emacsclient -a emacs -n ' and include (server-start) in my emacs init scripts. This enables me to open a file from the commandline using ec filename regardless if emacs is or is not already running.
Another tip: When you launch the emacs via Applications or open, emacs does not inherit the same path as you have in your terminal environment, so one thing I have found very useful is to run the following in my .profile after setting my path to change the PATH inherited cocoa applications:
defaults write ${HOME}/.MacOSX/environment PATH "$PATH"
That will work. If this is a native mac application, the binary is actually located under the application directory (not the capitalization of the binary): .../Emacs.app/Contents/MacOS/Emacs
Since you are coming from linux, you might be interested in MacPorts. This is a large collection of packages ported from linux. It allows packages to be installed and upgraded from the command line, doe sdependancy management, all the stuff you would expect. It includes a native version of Emacs, that can be invoked from the command line.

Resources