Where should I put a template folder for a bash script? - macos

I'm on OS-X (Mavericks, if that matters), and I'm making a bash script that will use resources from a folder called "templates". I'm trying to figure out where I should put it (the templates folder). I'd like to make it so the user doesn't need to modify their path when they install it, so I'd rather not do it the way the terminal mysql command does it (it lives in a folder in /usr/local/mysql/bin). I really want to be able to put them into usr/bin, but I don't know if it's "polite" to put folders in there (I don't see any in there).
Right now I'm leaning towards putting the scripts in usr/bin and having the templates in usr/lib. Is that how this type of thing is normally done, or is there another way? I'd like to follow a convention, assuming there is one. I'd also like it to apply to as many Unix platforms as possible (I'd like to put in a directory where bash scripts live that's consistent across as many Unix platforms as possible). Thanks.

If you follow the Filesystem Hierarchy Standard (FHS), your executable goes in /usr/local/bin, while read-only template files go in /usr/local/share/YOURAPP/. To quote the FHS:
/usr/local/share
The requirements for the contents of this directory are the same as /usr/share. […]
and:
The /usr/share hierarchy is for all read-only architecture independent data files.
(Emphasis added)
If the system admin is meant to customize the template files to take effect system-wide, then they would simply go in /etc/YOURAPP/templates (or something like that).
If the template files are customized on a per-user basis, then the modified copies of the templates (copied from /usr/local/share/YOURAPP/templates) need to be saved in the user's directory, under $HOME/.config/YOURAPP/templates or something like that (thanks to technosaurus for the correction).
You mentioned that you want to install the templates in a directory alongside your executable. That is not the standard approach on UNIX, at least going by the FHS. If you really want to go this route, there is a sort of convention of installing your app to /opt/YOURAPP/, using whatever organization you want inside that folder.
In all cases, it is not good practice to install executables directly to /usr/bin, as that directory is considered to be under the exclusive control of the OS/distribution. If you want to install there, the accepted way to do that is to create a package for the package manager of every supported OS/distribution.

Related

How to reliably refer to static file in a Go application?

I am writing a Go command-line tool that generates some files based on templates.
The templates are located in the Git repository alongside the code for the command-line tool itself.
I wanted to allow the following:
The binary, wherever it is called from, should always find the templates directory.
The templates directory can be overriden by the user if need be.
Since this is a Go application, I went with something like:
templateRoot := filepath.Join(
os.Getenv("GOPATH"),
"src/github.com/myuser/myproject/templates",
)
But being rather new to Go, I wonder if this approach is reliable enough: is it guaranteed that my application template will always be accessible at that path ?
What if someone vendorize my application into their own project ? Does that even make sense for a command-line tool ?
Because of 2., I obviously can't/won't use go-bindata because I want to allow for the templates to be overriden if need be.
In summary: what is a good strategy to reliably refer to non-go, static files in a Go command-line tool ?
GOPATH is used for building the application. While you could look for GOPATH and check relative locations to each GOPATH entry at runtime, you can't be sure it will exist (unless of course you make it a prerequisite for running your application).
go get itself is a convenience for developers to fetch and build a go package. It relies on having a GOPATH (though there's a default now in go1.8), and GOBIN in your PATH. Many programs require extra steps not covered by the simple go tool, and have scripts or Makefiles to do the build. If you're targeting users that aren't developers, you need to provide a way to install into standard system paths anyway.
Do what any regular program would do, and use some well-known path to locate the template files. You can certainly add some logic in your program to check for a hierarchy of locations: relative to $GOPATH, relative to the binary, working directory, $HOME, etc; just provide a list of locations to the user that your program will look for templates.

Trying to Set a Shortcut to a Directory

Im trying to run several different scripts on my Mac for data stored in different paths. So I put all said scripts into a folder. In order for a script to work, I have to be cd'd to a specific folder required for said script. I use the scripts to get different types of output (ex: Image volumes, MRI info, etc..).
I was wondering if there was a way to store all my scripts in one directory and assign a shortcut to it. That way, I can cd to my folder, and only type something like $ScriptsFolder/Script_1 to have it. Ive seen this done in the FSL software package, where typing $FSLDIR/data/standard would give you the items in that folder.
UPDATE:
Im using Script=/Users/ray/Documents/Script which works until I close down my terminal to start a new one. Any way to make the setup permanent?
EDITED
Found this helpful in the end.
http://www.techradar.com/how-to/computing/apple/terminal-101-creating-aliases-for-commands-1305638
I used it to create a shortcut to my scripts which are all placed in a folder for easy referencing.

Effective way of distributing go executable

I have a go app which relies heavily on static resources like images and jars. I want to install that go executable in different platforms like linux, mac and windows.
I first thought of bundling the resources using https://github.com/jteeuwen/go-bindata, but since the files(~100) have size ~ 20MB or so, it takes a really long time to build the executable. I thought having a single executable is an easy way for people to download the executable and run it. But seems like that is not an effective way.
I then thought of writing a installation package for each of the platform like creating a .rpm or .deb packages? So these packages contain all the resources and puts it into some platform specific pre defined locations and the go executable can reference them. But the only thing is that I have to handle that in the go code. I have to see if it is windows then load the files from say c:\go-installs or if it is linux then load the files from say /usr/local/share/go-installs. I want the go code to be as platform agnostic as it can be.
Or is there some other strategy for this?
Thanks
Possibly does not qualify as real answer but still…
As to your point №2, one way to handle this is to exploit Go's way to do conditional compilation: you might create a set of files like res_linux.go, res_windows.go etc and put a set of the same variables in each, pointing to different locations, like
var InstallsPath = `C:\go-installs`
in res_windows.go and
var InstallsPath = `/usr/share/myapp`
in res_linux.go and so on. Then in the rest of the program just reference the res.InstallsPath variable and use the path/filepath package to construct full pathnames of actual resources.
Of course, another way to go is to do a runtime switch on runtime.GOOS variable—possibly in an init() function in one of the source files.
Pack everything in a zip archive and read your resource files from it using archive/zip. This way you'll have to distribute just two files—almost "xcopy deployment".
Note that while on Windows you could just have your executable extract the directory from the pathname of itself (os.Args[0]) and assume the resource file is located in the same directory, on POSIX platforms (GNU/Linux and *BSD etc) the resource file should still be located under /usr/share/myapp or a similar place dictated by FHS (or particular distro's rules), so some logic to locate that file will still be required.
All in all, if this is supposed to be a piece of FOSS, I'd go with the first variant to let the downstream packagers tweak the pathnames. If this is a proprietary (or just niche) software the second idea appears to be rather OK as you'll play the role of downstream packagers yourself.

wxWidgets: Preferred way to name .po/.mo files: en/app.mo or en.mo?

My application is to be written using wxWidgets, but the question may be related to using gettext in general.
For the application named app, some sources suggest I sould create <lang>/ subdirectory, create the app.po file inside with the translation, and convert it to the distributed app.mo file in the subdir.
Another approach is to create app.pot (i.e. the template from the sources via xgettext), and to msginit and msgmerge it to the <lang>.po for the language.
For the first approach, more .mo files can be put inside the <lang>/ subdirectory. Also the wxLocale::AddCatalog() gets the domain name (where the domain can naturally be app, wxstd, etc.). On the other hand, the <lang>.po file name is descriptive on itself -- wherever it is located.
What are the pros and cons of the two approaches? Is there any text that explains the path to be chosen?
Thanks for your time and experience,
Petr
The Unix convention is to use app.mo for binary catalogs, see the contents of /usr/share/locale directory. Sometimes lang.po is however used for the source ones, as done in wxWidgets itself (see its locale subdirectory), but they're still installed into language-specific subdirectory using the app-dependent name.

How to design software for Linux in relation to Windows?

I have an application that I've written for Windows which I am porting to Linux (Ubuntu to be specific). The problem is that I have always just used Linux, never really developed for it. More specifically, I dont understand the fundamental layout of the system. For example, where should I install my software? I want it to be accessible to all users, but I need write permission to the area to edit my data files. Furthermore, how can I determine in a programmatic way, where the software was installed (not simply where its being called from)? In windows, I use the registry to locate my configuration file which has all of the relevant information, but there is no registry in Linux. Thanks!
The Filesystem Hierarchy Standard (misnamed -- it is not a standard) will be very helpful to you; it clearly describes administrator preferences for where data should live.
Since you're first packaging your software, I'd like to recommend doing very little. Debian, Ubuntu, Red Hat, SuSE, Mandriva, Arch, Annvix, Openwall, PLD, etc., all have their own little idiosyncrasies about how software should be best packaged.
Building
Your best bet is to provide a source tarball that builds and hope users or packagers for those distributions pick it up and package it for you. Users will probably be fine with downloading a tarball, unpacking, compiling, and installing.
For building your software, make(1) is the usual standard. Other tools exists, but this one is available everywhere, and pretty reasonable. (Even if the syntax is cranky.) Users will expect to be able to run: make ; make install or ./configure ; make ; make install to build and install your software into /usr/local by default. (./configure is part of the autotools toolchain; especially nice for providing ./configure --prefix=/opt/foo to allow users to change where the software gets installed with one command line parameter. I'd try to avoid the autotools as far as you can, but at some point, it is easier to write portable software with them than without them.)
Packaging
If you really do want to provide one-stop-packaging, then the Debian Policy Manual will provide the canonical rules for how to package your software. The Debian New Maintainers Guide will provide a kinder, gentler, walkthrough of the tools unique to building packages for Debian and Debian-derived systems.
Ubuntu's Packaging Guide may have details specific to Ubuntu. (I haven't read it yet.)
Configuration
When it comes to your application's configuration file, typically a file is stored in /etc/<foo> where <foo> represents the program / package. See /etc/resolv.conf for details on name resolution, /etc/fstab for a list of devices that contain filesystems and where to mount them, /etc/sudoers for the sudo(8) configuration, /etc/apt/ for the apt(8) package management system, etc.
Sometimes applications also provide per-user configuration; those config files are often stored in ~/.foorc or ~/.foo/, in case an entire directory is more useful than a file. (See ~/.vim/, ~/.mozilla/, ~/.profile, etc.)
If you also wanted to provide a -c <filename> command line option to tell your program to use a non-standard configuration file, that sometimes comes in real handy. (Especially if your users can run foo -c /dev/null to start up with completely default configuration.)
Data files
Users will store their data in their home directory. You don't need to do anything about this; just be sure to start your directory navigation boxes with getenv("HOME") or load your configuration files via sprintf(config_dir, "%s/%s/config", getenv("HOME"), ".application"); or something similar. (They won't have permissions to write anywhere but their home directory and /tmp/ at most sites.)
Sometimes all the data can be stored in a hidden file or directory; ssh(1) for example, keeps all its data in ~/.ssh/. Typically, users want the default kry name from ssh-keygen(1) so ssh-agent(1) can find the key with the minimum of fuss. (It uses ~/.ssh/id_rsa by default.) The shotwell(1) photo manager provides a managed experience, similar to iPhoto.app from Apple. It lets users choose a starting directory, but otherwise organizes files and directories within as it sees fit.
If your application is a general purpose program, you'll probably let your users select their own filenames. If they want to store data directly to a memory stick mounted in /dev or /media or a remote filesystem mounted into /automount/blah, their home directories, a /srv/ directory for content served on the machine, or /tmp/, let them. It's up to users to pick reasonable filenames and directories for their data. It is up to users to have proper permissions already. (Don't try to provide mechanisms for users to write in locations they don't have privileges.)
Application file installation and ownership
There are two common ways to install an application on a Linux system:
The administrator installs it once, for everyone. This is usual. The programs are owned by root or bin or adm or some similar account. The programs run as whichever user executes them, so they get the user's privileges for creating and reading files. If they are packaged with distribution packaging files, executables will typically live in /usr/bin/, libraries in /usr/lib/, and non-object-files (images, schemas, etc.) will live in /usr/share/. (/bin/ and /lib/ are for applications needed at early boot or for rescue environments. /usr might be common to all machines in a network, mounted read-only late in the boot up process.) (See the FHS for full details.)
If the programs are unpackaged, then /usr/local/ will be the starting point: /usr/local/bin/, /usr/local/lib/, /usr/local/share/, etc. Some administrators prefer /opt/.
Users install applications into their home directory. This is less common, but many users will have a ~/bin/ directory where they store shell scripts or programs they write, or link in programs from a ~/Local/<foo>/ directory. (There is nothing magic about that name. It was just the first thing I thought of years ago. Others choose other names.) This is where ./configure --prefix=~/Local/blah pays for itself.)
In Linux, everything is text i.e. ASCII.
Configuration is stored in configuration files which normally have .conf extension and stored in /etc folder.
The executable of your application normally resides in /usr/bin folder. The data files of your application can go to /usr/lib or folder in /usr/ folder.
It is important to consider which language you are writing your application in. In C/C++ a custom makefile is used to do installation which copies these files in respective folders. The location of installation can be tracked by tracking the .conf file and storing the location while generation using bash script.
You should really know bash scripting in order to automate this everything.

Resources