4

Is there any way to make a background process in Mathematica so that the external command will run but not hold up other evaluations?

startTime = AbsoluteTime[];
Run["sleep 2" (*, a magic option here perhaps? *)];
AbsoluteTime[] - startTime
(* Returns 2.016960 on my system *)

I want a version of / option for Run that will not hold up the evaluation, so that the last line in the above code will return something close to zero.

(The above will run in *nix and OSX; there doesn't seem to be any universal/portable way to "sleep 2" in a DOS/Windows shell: Sleeping in a batch file. Although, perhaps the easiest way to get the sleep command is to install the MS resource kit - see this answer to the Sleeping in a batch file question or the comments below.)


At the moment, the reason I want this is so that my ALSASound command given in No sound in Mathematica under linux will not stop the fireworks. But it would also be a good improvement to ALSASound and a useful thing to know in general.


Edit

The two solutions posted below rely on using the shell to spawn a new/child process using start cmd in Windows/DOS and cmd& in *nix. Is there a platform independent and/or Mathematica based solution? (Points will be awarded for the creation of a command that checks the OS using $OperatingSystem!)

Community
  • 1
  • 1
Simon
  • 14,631
  • 4
  • 41
  • 101
  • Sleep in Windows:http://malektips.com/xp_dos_0002.html – Dr. belisarius Jul 05 '11 at 01:25
  • @belisarius: The `sleep` command is not there by default, it requires the installation of the Resource Kit... – Simon Jul 05 '11 at 01:28
  • yep. I posted the pointer to the (free) MS resource kit – Dr. belisarius Jul 05 '11 at 01:29
  • @Simon - I'm late to the discussion, so forgive me if these are silly suggestions... (1) Couldn't you just operate using two kernels? One for your main work and one for background-type processes? (perhaps controlled via ScheduledTasks---even though you say you want to avoid this) – telefunkenvf14 Jul 10 '11 at 03:25
  • @telefunkenvf14: Maybe - but I'm more interested in running/creating background non-mathematica processes... – Simon Jul 11 '11 at 06:02
  • @Simon - Right. I think I understand. Couldn't you just use the spare kernel (and scheduled tasks of some sort) to fire off the OS or external program commands you wanted? BTW, I noticed that the new GridManager was released yesterday. If I recall correctly, this gives you an extra 4 compute kernels. (dunno if you have v8 or PremierService) – telefunkenvf14 Jul 14 '11 at 12:26

3 Answers3

4

As Simon points out, Switch is the correct tool for procedural conditions and is more appropriate than Piecewise. Here's the same solution using Switch:

BackgroundProcess[proc_String] := 
  Switch[$OperatingSystem, 
    "MacOSX" | "Unix", Run["(" <> proc <> ")&"], 
    "Windows", Run["start /b " <> proc],
     _, $Failed]

You could write a wrapper function like so that handles multiple OSes.

BackgroundProcess[proc_String] := 
 Module[{
  command = Piecewise[{
       {proc <> " &", $OperatingSystem == "MacOSX" || "Unix"}, 
       {"start /b " <> proc, $OperatingSystem == "Windows"}
     }]
    }, 
  Run[command]]

The /b after start runs the process in the background, without spawning a new command window and the output is printed to stdout. You can then build upon this to include error messages, some input sanitization (e.g., don't allow rm and the like) if you want that, and you should be all set.

A predefined function from Mathematica (if it existed) is probably going to be along these lines. Background processes are inherently OS dependent, so there is no real "platform independent" way of doing it. Any implementation that claims to be so (like the os module in python) is basically a set of rules defined for each possible OS known to exist, so that you don't really have to worry about the finer details.

abcd
  • 41,765
  • 7
  • 81
  • 98
  • Sure, I understand - this is also how I imagine the file system commands in Mma to be implemented. And this is basically what I had in mind in the Edit section to the question (so +1). Although I think that `Which` or `Switch` is more appropriate than `Piecewise` for this type of function. – Simon Jul 05 '11 at 02:43
  • `Switch` returns unevaluated if no match is found, whereas with `Piecewise`, you can have a default value which could be an error message. But I could be wrong about it... in any case, `Which`, `Switch`, `If`, `Piecewise`, take your pick :) – abcd Jul 05 '11 at 02:47
  • With `Switch` you can make the last term match everything using `_`, with `Which` you can use `True` and with `If` you have the optional 4th argument. I normally think of `Piecewise` as being used for mathematics, while the others are used for programming/flow control. – Simon Jul 05 '11 at 02:49
  • I'd probably write the command as `BackgroundProcess[proc_String] := Switch[$OperatingSystem, "MacOSX" | "Unix", Run["(" <> proc <> ")&"], "Windows", Run["start /b " <> proc], _, $Failed]`, but I can't test the Windows part on my system. – Simon Jul 05 '11 at 03:05
  • Ah, yes you can use the `_` with `Switch` to capture everything else... I don't have windows either, but it does work on a Mac. Perhaps belisarius/Sjoerd can test it when they see it. – abcd Jul 05 '11 at 03:12
  • 1
    I do not want to move this to chat :/ – abcd Jul 05 '11 at 03:12
  • Also, out of curiosity, do you prefer `Switch` because there is something wrong with `Piecewise` or just because it simply wasn't designed for this? I'm asking because I'm not that well versed with the internals of these functions and there might be something that I'm completely overlooking... – abcd Jul 05 '11 at 03:15
  • I just assumed that since `Piecewise` is a [mathematical function conditional instead of a procedural conditional](http://reference.wolfram.com/mathematica/guide/Conditionals.html) that it has more overhead and things that could go wrong. I feel more comfortable using [the right tool for the job](http://drdobbs.com/184415067). This might be worth a question of its own - maybe someone knows where (other than in mathematical functions) this choice makes a significant difference. – Simon Jul 05 '11 at 03:29
  • Ah, alright. I'll update the answer with the `Switch` version. – abcd Jul 05 '11 at 03:36
  • 2
    @Simon I'll try to state my point clearly, if my poor's man English allows me. There are many OSs out there where the "fork" primitive is simply non existent. You shouldn't ask Mma to implement a full OS concept so that you can spawn a new process (or a child) if the OS does not support that. Mma provides a full set of communication primitives to allow you to establish inter-process communication, and setting up a server so that you can manage the process synch, start and end the way you want to. – Dr. belisarius Jul 05 '11 at 04:04
1

In Windows (Did I understand what you are trying to do ??)

startTime = AbsoluteTime[];
Run["start notepad"];
AbsoluteTime[] - startTime
(*
-> 0.1406250
*)

Edit

For portability reasons, I don't think Mma should assume particular features of the underlying OS. Having a Standard Input and Output, and a Command shell callable from inside a program is enough. Once you get control passed to the OS shell of your choice, do whatever you want (call start or submit &, for example) or what your OS allows you to do.

Dr. belisarius
  • 60,527
  • 15
  • 115
  • 190
  • Yes and no. I think that the command `start` spawns a new (or maybe child) process. This is basically the solution that I thought of after posting the question. There's a deleted answer I know you can see. It would also be nice if there is a Mathematica based, platform independent solution - i.e. one that does not depend on using `start` for windows or `&` in *nix. – Simon Jul 05 '11 at 01:30
  • @Simon I do not comment neither on invisible nor on shameful answers :) – Dr. belisarius Jul 05 '11 at 01:32
  • @Simon Seriously. Is it not what your are trying to do? Perhaps I am missing something – Dr. belisarius Jul 05 '11 at 01:33
  • Yes. It is what I was trying to do. Your answer provides a Windows solution, mine provides a *nix solution. Is there a platform independent / Mathematica based solution? – Simon Jul 05 '11 at 01:36
  • @Simon I assume you don't want to use `ScheduledTasks[]`. Do you? – Dr. belisarius Jul 05 '11 at 01:41
  • (almost) simultaneous edits. I think that just like Mathematica has platform independent file system commands, it would be nice to have platform independence as widely as possible. What's the point in having such a behemoth program if you can't give your notebooks to all of your friends? – Simon Jul 05 '11 at 02:14
  • @Simon Mma has it, but via xLink, which obscures completely the underlying OS, as it should be. There is no point in allowing you to access (say) shared memory, if your friend's machine is a mainframe. – Dr. belisarius Jul 05 '11 at 02:19
0

Although I don't know a Mathematica way of doing this, there is a very simple BASH/shell solution: just create a a child process using "&".

Then

startTime = AbsoluteTime[];
Run["(sleep 20)&"];
AbsoluteTime[] - startTime
(* Returns approx 0.01 *)

A similar solution works with my ALSASound command and I've updated my answer.

Community
  • 1
  • 1
Simon
  • 14,631
  • 4
  • 41
  • 101