Package bash script in "executable" for double-click execution (ideally platform independent)? - bash

I wrote a number of bash scripts that greatly simplify the routine, but very tedious, file manipulation that my group does.
Unfortunately, most in my group cannot open a terminal, let alone run scripts with complex arguments.
Is there a way to nicely package a bash script into an executable (that accepts arguments) that runs nicely on multiple computer platforms?
I run Mac OS X, but many of my colleagues run Windows (which can run bash scripts via Cygwin, etc.). I am aware of Platypus, but is there an equivalent for Windows?

I do not know if it meets all of your requirements but I use makeself wich is really great to package things. It works with cygwin, so it might fill in your needs ^^
Basically, when you create a makeself archive, you give a script that will be executed when the archive is "launched". This script get all the parameters given to the archive (whatever you want) :
makeself.sh ${dir_to_archive} ${name_of_archive} ${description} ${startup_script}
When you run the auto-extractible archive, you do :
my_archive.run ${param1} ${param2} ${paramN}
It will uncompress your archive and run :
${startup_script} ${param1} ${param2} ${paramN}
my2c

Related

Coding a relative path to file in OS X [duplicate]

I have a Haskell script that runs via a shebang line making use of the runhaskell utility. E.g...
#! /usr/bin/env runhaskell
module Main where
main = do { ... }
Now, I'd like to be able to determine the directory in which that script resides from within the script, itself. So, if the script lives in /home/me/my-haskell-app/script.hs, I should be able to run it from anywhere, using a relative or absolute path, and it should know it's located in the /home/me/my-haskell-app/ directory.
I thought the functionality available in the System.Environment module might be able to help, but it fell a little short. getProgName did not seem to provide useful file-path information. I found that the environment variable _ (that's an underscore) would sometimes contain the path to the script, as it was invoked; however, as soon as the script is invoked via some other program or parent script, that environment variable seems to lose its value (and I am needing to invoke my Haskell script from another, parent application).
Also useful-to-know would be whether I can determine the directory in which a pre-compiled Haskell executable lives, using the same technique or otherwise.
As I understand it, this is historically tricky in *nix. There are libraries for some languages to provide this behavior, including FindBin for Haskell:
http://hackage.haskell.org/package/FindBin
I'm not sure what this will report with a script though. Probably the location of the binary that runhaskell compiled just prior to executing it.
Also, for compiled Haskell projects, the Cabal build system provides data-dir and data-files and the corresponding generated Paths_<yourproject>.hs for locating installed files for your project at runtime.
http://www.haskell.org/cabal/release/cabal-latest/doc/users-guide/authors.html#paths-module
There is a FindBin package which seems to suit your needs and it also works for compiled programs.
For compiled executables, In GHC 7.6 or later you can use System.Environment.getExecutablePath.
getExecutablePath :: IO FilePathSource
Returns the absolute pathname of the current executable.
Note that for scripts and interactive sessions, this is the path to the
interpreter (e.g. ghci.)
There is executable-path which worked with my runghc script. FindBin didn't work for me as it returned my current directory instead of the script dir.
I could not find a way to determine script path from Haskell (which is a real pity IMHO). However, as a workaround, you can wrap your Haskell script inside a shell script:
#!/bin/sh
SCRIPT_DIR=`dirname $0`
runhaskell <<EOF
main = putStrLn "My script is in \"$SCRIPT_DIR\""
EOF

Cross-platform command line script (e.g. .bat and .sh)

I noticed that Windows 7 enables to execute .sh files as if they were .bat files. That got me wondering whether it is possible to write a .sh file such that it can be executed in Windows and Linux (let's say bash).
The first thing that comes to my mind is to fabricate an if-statement such that Windows and Ubuntu can deal with it and jump into the according block to execute plattform-specific commands. How could this be done?
Note: I know this is not good practice. I also know that scripting languages like Python are far better suited to solve this problem than a mixed-syntax command line script would be. I'm just curious...
You could use this:
rem(){ :;};rem '
#goto b
';echo sh;exit
:b
#echo batch
It's valid shell script and batch, and will execute different blocks depending on how it's run.
Modify the echo and #echo lines to do what you want.
AFAIK, you can't directly run .sh files from Windows' cmd.exe. For that you'll need a *nix emulation layer to run the shell. Check out Cygwin or Msys/MinGW

How Secure is using execFile for Bash Scripts?

I have a node.js app which is using the child_process.execFile command to run a command-line utility.
I'm worried that it would be possible for a user to run commands locally (a rm / -rf horror scenario comes to mind).
How secure is using execFile for Bash scripts? Any tips to ensure that flags I pass to execFile are escaped by the unix box hosting the server?
Edit
To be more precise, I'm more wondering if the arguments being sent to the file could be interpreted as a command and executed.
The other concern is inside the bash script itself, which is technically outside the scope of this question.
Using child_process.execFile by itself is perfectly safe as long as the user doesn't get to specify the command name.
It does not run the command in a shell (like child_process.exec does), so there is no need to escape anything.
child_process.execFile will execute commands with the user id of the node process, so it can do anything that user could do, which includes removing all the server files.
Not a good idea to let user pass in command as you seem to be implying by your question.
You could consider running the script in a sandbox by using chroot, and limiting the commands and what resides on the available file system, but this could get complet in a hurry.
The command you pass will get executed directly via some flavor of exec, so unless what you trying to execute is a script, it does not need to be escaped in any way.

How To Run This Script More Easily

I have a Ruby script that I wrote that sorts some files in a jumble of directories based on it's file extension. It would be very difficult to sort it using a GUI, and its easier for me to just put the file in the topmost directory and let the sorter do the work.
Problem is, I'm a bit of a noob to unix scripting. What I want to be able to do is be able to run that sorter script from anywhere on my computer, without having to
cd Desktop/Whatever/Foo
ruby sorterscript.rb
just write sortfolders at the commandline and have the program be run.
I've tested the script many times, and it works fine, I just want a bit more convenience.
Bonus: If possible, and not too difficult, it would be even better if I could have the program run, say, every hour automatically.
As far as your first question goes, you need to do couple of things:
Add a shebang line to your script (make it the first line of the script):
#!/usr/bin/ruby (or whatever the path to the Ruby interpreter's executable is, I forget its exact location)
Make the script executable, either via the Finder's "Get Info" context menu, or via the command line, for example:
chmod 755 my_script.rb
Add the directory location of your script to the PATH environment variable to OS X's launchd.conf file, as described here. You need to add this line:
setenv PATH /path/to/my/script:$PATH (substitute the real path to your script)
As far as your bonus question goes, you can use cron to set up a recurring job. I never really do this, but here's Apple's cron man page to get you started.

Is it possible to override hashbang/shebang path behavior

I have a bunch of scripts (which can't be modified) written on Windows. Windows allows relative paths in its #! commands. We are trying to run these scripts on Unix but Bash only seems to respect absolute paths in its #! directives. I've looked around but haven't been able to locate an option in Bash or a program designed to replace and interpreter name. Is it possible to override that functionality -- perhaps even by using a different shell?
Typically you can just specify the binary to execute the script, which will cause the #! to be ignored. So, if you have a Python script that looks like:
#!..\bin\python2.6
# code would be here.
On Unix/Linux you can just say:
prompt$ python2.6 <scriptfile>
And it'll execute using the command line binary. I view the hashbang line as one which asks the operating system to use the binary specified on the line, but you can override it by not executing the script as a normal executable.
Worst case you could write some wrapper scripts that would explicitly tell the interpreter to execute the code in the script file for all the platforms that you'd be using.

Resources