I'm writing a small script to manage my installed JDK on a linux machine, say for example that the name of the script/function is usejdk.
I come with to ways :
usejdk is a bash function in shell script sourced the file in .bashrc or .bash_profile.
use usejdk as the name of the shell script and add it to the ~/bindirectory which is the PATH.
What is the idiomatic way to deploy a shell script on a unix machine between the two ?
If you are creating something for other people to use, a self-contained script they can put in their PATH and replace with new versions as needed is far easier, better, and maintainable than a function that will require them editing their startup files.
Related
I have been working on a node script that does the installation of external dependencies and was wondering if its possible to set the PATH variable using Node.
For example, If I want to install Go using script, I can execute command brew install Go and this works but when I do export GOPATH=$PATH, this is never set.
I also tried using process.env but this also does not work. Also my assumption with process is that it must run in a sandbox. So it will not update/ set anything outside.
So the question is, can I do this? If yes, how?
It is not possible in any programming language. At least on Unix (BSD, MacOS, Illumos etc.) and Linux, I'm not sure about Windows.
As a security feature, Unix processes are designed such that they cannot touch the environment of their parent's process. Only the parent process can influence the environment of their children.
When you are on a command line you are running a shell program (either Bash or Korn Shell or TCSH or Fish etc.). When you execute something on the command line such as a node.js script or Google Chrome or Minecraft these programs will be the children to your shell program. On Unix and Linux these child programs inherit their parent's environment.
That is why you can export environment (global) variables and your programs can access them. However, this relationship is one-way and it was designed that way on purpose.
You may notice that in shell scripts you can "save" commands to set environment variables in a file. For example in Bash you sometimes see people do this:
# variables.sh
export HELLO "World"
However, this will not work if you execute the script as a script:
$ bash variables.sh
$ echo $HELLO
<--------------------- nothing is displayed here
the variable is not exported
You sometimes see people do this instead:
$ . variables.sh
$ echo $HELLO
World
And you may wonder how that works. Well.. in some shell languages the dot command imports the script instead of executing the script as a separate process. Think of it like import or require() in javascript.
Of course, Bash does not understand javascript syntax. It also does not understand C++ or Java or Ruby or PHP. It only understands Bash syntax.
So the longer answer is it is not possible in any programming language except for the language of the shell you are using (eg. if you are using Fish you need to write a script in Fish syntax or if you are using Ksh you need to write a script in Korn syntax).
My teacher gave us this assignment to create our own shell. Our shell is supposed be called rshell and is supposed to work like the regular shell.
I created my own shell using C++. If you type a command like ls in my created shell it gives you a list just like how if you typed ls in the regular shell.
The problem I am facing is how do I get the .sh files or script files to work with my created shell. I noticed when I run a .sh file using my shell it does not run the .sh file through my shell. It runs it through the regular shell. How do I make .sh files run through my shell?
Change the hash-bang line of the scripts to point at your shell. For instance,
#!/usr/local/bin/rshell
Or wherever your shell executable is.
As John already said, change the shebang to point to your shell. The kernel will invoke the command in the shebang with the file itself as an argument. To demonstrate, try a file with a shebang of #!/bin/cat.
#!/bin/cat
hello world
It pretty much behaves the same as if you typed /bin/cat /path/to/file.
The shebang does not have PATH lookup capabilities, so #!yourshell would not work as a shebang. However, you can use env to do the PATH lookup as in #!/usr/bin/env yourshell. (This approach is preferred for commands that are at different paths on different systems, like python.)
I was working on this tutorial here and I want to know the path so I can put it in my shell scripts on the top line as is good practice.
I was told this is not accurate:
echo "$SHELL"
What is the correct way to determine the path to the interpreter for shell scripts?
This is a shared hosting account and it is not obvious where it is located.
This is a follow up to a similar but not duplicate here.
You can use
which -a bash
to list all paths for the current user that point to a bash program.
When beginning to work, I have to run several commands:
source work/tools
cd work/tool
source tool
setup_tool
Off course, doing this a few times a day is really annonying, so I tried to make a bash script tool where I put these commands and put it in /user/bin to run it with command
tool
However, there is a problem. When i run the script and then try to work by typing some of the tool-based commands, it does not work.
I figured out, that it is fine, since if I make a script and then run it, the script seems to run in the same terminal window, but what it really does is, that it behaves as if it created a "hidden window" for its execution and after termination of the script, the "hidden window" terminates too. So I am asking - is there a way to automatize the source command?
I have tried using xterm -hold -e command, but it runs the programmed script in the new window. Obviously, I don't want that. How can I achieve running it in the current window?
Don't put files like that in /usr/bin. As a general rule you don't want to mess with the distribution owned locations like that. You can use /usr/local/bin if you need a system-wide location or you can create a directory in your home directory to hold things like this that are for your own usage (and add that to the $PATH).
What you've noticed is that when run as a script on its own (tool, /path/to/tool, etc.) that the script runs in its own shell session (nothing to do with terminal windows as-such) and you don't want that (as the changes the script makes don't persist to your current shell session).
What you want to do instead is "source"/run the script in your current session. Which you are already doing with that set of commands you listed (source work/tools is doing exactly that).
So instead of running tool or /path/to/tool instead use source /path/to/tool or . /path/to/tool.
As fedorqui correctly points out you don't even need a script for this anywhere as you can just make a shell function for this instead (in your normal shell startup files .bashrc, etc.) and then just run that function when you need to so that setup.
Be careful to use full paths for things when you do this though since you, presumably, want this to work no matter what directory you happen to be in when you run it.
It doesn't create a new hidden window, nor does it create a terminal. What happens is that if you're running a script, normally it runs on a new shell process. The script you're running is supposed to modify the shell environment, but if you're running the script in a new shell process, that shell process's environment is the one that gets modified, instead of your shell environment.
Scripts that needs to modify the current shell environments usually must be run with the source command. What you need to do is to run the script in the current shell. So you should do source /path/to/tool.
If you want to be able to source the script with just tool, put this in your alias file/shell startup (check your distro doc where the file is, but it's usually either .bash_aliases or .bashrc):
alias tool="source /path/to/tool"
Sorry, the headline might be a bit irritating, but I didn't know anything better. Anyway, I want a bash script to work on FreeBSD, OpenBSD and Linux without modifying it, but bash isn't located at the same place in Linux and BSD.
So, if I write #!/bin/bash then it won't work on BSD, because the bash shell is located in /usr/local/bin/bash there. Is there any solution to get this script working on both?
Or do I really need to ship two scripts with different paths...?
Using env in the shebang (#!/usr/bin/env bash) should make the script OS agnostic.
I like the answer about using #!/usr/bin/env bash
It is an interesting and excellent answer, but that would only work if bash is in the path.
Another option might be to use #!/bin/sh which is the most universally compatible shell location.
Then, have the script do something in sh, such as check where bash is installed (if bash is even installed). Another option might be to have bash exist to both locations. Making another installation may sound like overkill, but this goal could be accomplished as simply as creating a hard link so that bash actually exists in both locations.