Bash - Remote Library - bash

We're two student working on a Bash Tools Box, and we come across a problem :
Our local script use functions, stocked in two local libraries.
Our script uses functions inside the first library, and this last uses functions inside the second one library.
Script <-- Library1 <-- Library2
We can't fusion the two libraries in one.
We actually use this command to run our script on a remote computer :
ssh login#remoteIP bash < ~/script.sh
The question is : How to set in the script the library location

You need to use the . command in order to include external libraries. Yes, the command is simply called . - a literal dot. In library1.sh add at the top:
. /path/to/library2.sh
In script.sh add at the top:
. /path/to/library1.sh
I would recommend to use absolute paths since relative paths. If you use relative paths, you need to make sure that they are relative to one of your $PATH entries otherwise they would be relative to the current folder where script.sh gets executed.
Btw, there is also the source command which is doing excatly the same as the dot command. Both of them are bash builtins.
Type help . or help source to get help.

Embed your Library# code in your script using bashpp.
Replace your . calls with #include and then run it through bashpp:
bashpp ~/script.sh | ssh login#remoteIP bash -s

Related

How to get the absolute path of a script using its PPID - Bash

I am trying the absolute path of a given PPID from a shell script.
However, the Parent Process may be any type of script (bash/csh/zsh/tsh/Makefile).
The child process is always a bash script and is the only script I have access on to edit.
I have tried:
ps --no-headers -o command $PPID but it only gets the command that invoked the parent process. This isn't what I need because the parent may have caused some cd's inside the script and I won't be able to resolve the relative path in the command to it.
ls -l /proc/$PPID/fd/255 and this was the closest to what I want but this is specific to bash scripts and as I mentioned, I don't have access to know my parent process' script type.
/proc/$PPID/exe returns the binary exe, and I need the script's absolute path that is using this binary.
There isn't such thing as "the" absolute path. There may be several way to access the same file. And some times, none of them (or more than one of them, depends how you look at it) are "the" main name.
I am thinking of hard links here, for example.
Makefile is never the path of a script. It is just a configuration file. That is read by default by the executable. Which is probably /usr/bin/make. To find a path to the Makefile file, you need to read arguments of make. Or to find a Makefile among open files (assuming there is only one, and that it is named Makefile, and that is not certain). And the strategy to guess what is the Makefile of a make process is specific to make. You need another strategy to guess what is the script file executed by a bash process, Another to find what is the python file executed by a python command (which could be a shebang python "executable", a python ../somerealtive/path/somefile.py a python /some/absolute/paht a python -m somemodele, a python -c "import somemod ; somemod.run()" etc.)
Now, since you've mentioned /proc/$PPID/exe, you can get the file "pointed" by this, using
path=$(readlink -f /proc/$PPID/exe)
Again, that is linux solution, more than a bash one. You have no guarantee from bash that the system on which you run this command have a /proc filesystem
I must add that I suspect a XY problem here. What are you trying to do exactly?

Mistake this is a duplicate [duplicate]

This question already has answers here:
How to obtain the first letter in a Bash variable?
(7 answers)
Closed 3 years ago.
I am trying to my a custom terminal command. I just learned I am supposed to do it using the Unix script? I don't really know much of what that is and am still trying to figure it out. What I do know is that $1 is an arg is it possible to make it a variable and then get the first letter like you could in python?
EX:
str = 'happy'
str[0] = 'h'
You're asking a few different things here.
I am trying to my a custom terminal command.
That could mean a few different things, but the most obvious meaning is that you want to add an executable to your path so that when you type it at the terminal, it runs just like any other executable on your system. This requires just a few things:
the executable permission must be set.
the file must specify how it can be executed. For interpreted programs such as bash scripts or python scripts, you can do so by beginning the file with a "shebang line" that specifies the interpreter for the file.
the file must be in one of the locations specified by your $PATH.
I just learned I am supposed to do it using the Unix script?
there's no such thing as a "unix script", but what you seem to be referring to is a "shell script". Though these are commonly associated with unix, they're no more inherently a unix script than any other language. A shell, such as bash, sh, or any other, is just an interpreted language that is designed so that it is convenient to be used interactively by a human as well as being programmatically executed as part of a saved file.
I don't really know much of what that is and am still trying to figure it out.
Let's get into some specifics.
First I edit a file called 'hello-world' to contain:
#!/bin/bash
echo "Hello, world!"
Note that this filename has no "extension". Though heuristics based on file extension are sometimes used (espeically in windows) to determine a file type, unix typically sees a file "extension" as part of the arbitrary file name. The thing that makes this a potentially executable bash script is the specification of that interpreter on the shebang line.
We can run our script right now from bash, just as we could if we wrote a python script.
$ bash hello-world
hello, world!
To make the bash implicit, we mark the file as executable. This enables the linux operating system to consult the beginning "magic bytes" of the file to determine how to run it. Thes beginning bytes might signify an ELF file (a compiled executable, written in eg C, C++, or go). Or, it might be #! which just so happens means , "read the rest of this first line to determine the command to run, and pass the rest of this file into that command to be interpreted.
$ chmod +x hello-world
ls -l will show us the "permissions" on the file (more accurately called the "file mode", hence chmod rather than chperm) . The x stands for executable, so we have enabled the use of the leading bytes to determine method of execution. Remember, the first two bytes of this file, and the rest of that first line, then specify that this file should be "run through bash" so to speak.
$ ls -l hello-world
-rwxr-xr-x 1 danfarrell staff 33 Dec 27 20:02 hello-world
Now we can run the file from the current directory:
$ ./hello-world
hello, world!
At this point, the only difference between this command and any other on the system, is that you have to specify its location. That's because my current directory is not in the system path. In short, the path (accessible in a unix shell via the $PATH variable) specifies an ordered list of locations that should be searched for a specified command whose location is not otherwise specified.
For example, there's a very common program called whoami. I can run it directly from my terminal without specifying a location of the executable:
$ whoami
danfarrell
This is because there's a location in my $PATH in which the shell was able to find that command. Let's take a closer look. First, here's my path:
$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/go/bin
And there's also a convenient program called whereis which can help show which path elements supply a named executable:
$ whereis whoami
/usr/bin/whoami
Sure enough, whoami is in one of the elements of the $PATH. (Actually I shared a simplified $PATH. Yours might be somewhat longer).
Finally, then, we can get to the last thing. If I put hello-world in one of the $PATH elements, I will be able to invoke it without a path. There are two ways to do this: we can move the executable to a location specified in the path, or we can add a new location to the path. For simplicity's sake I'll choose the first of these.
$ sudo cp hello-world /usr/local/bin/
Password:
I needed to use sudo to write to /usr/local/bin because it's not accessible as my user directly - that's quite standard.
Finally, I've achieved the goal of being able to run my very important program from any location, without specifying the executable's location.
$ hello-world
hello, world!
$ which hello-world
/usr/local/bin/hello-world
It works! I've created what might be described as a "custom terminal command".
What I do know is that $1 is an arg is it possible to make it a variable and then get the first letter like you could in python?
Well, one option would be to simply write the custom terminal command in python. If python is available,
$ which python
/usr/bin/python
You can specify it in a shebang just like a shell can be:
#!/usr/bin/env python
print("hello, world!"[0])
$ hello-world
h
it works!
Okay, confession time. I actually used #!/usr/bin/env python, not /usr/bin/python. env helps find the correct python to use in the user's environment, rather than hard coding one particular python. If you've been using python during the very long running python 2 to python 3 migration, you can no doubt understand why I"m reticent to hard code a python executable in my program.
It's certainly possible to get the first letter of a string in a bash script. But it's also very possible to write a custom command in a program other than shell. Python is an excellent choice for string manipulation, if you know it. I often use python for shell one-liners that need to interact with json, a format that doesn't lend itself well to standard unix tool stream editing.
Anyway, at the expense of incurring SO community's ire by reanswering an "already answered" question, I'll include a version in shell (Credit goes to David C Rankin)
#!/bin/bash
echo "${1:0:1}"
$ hello-world hiworld
h

How do I use SSFT (Shell Scripts Frontend Tool) on Ubuntu (or any Linux)?

I can't find a man page or any help for ssft. I want to use it in my bash scripts to select either kdialog (if on KDE) or zenity (if on gnome).
See Shell Scripts Frontend Tool
Surely the help pages are somewhere, but I must be overlooking them.
I am running Debian 6.0 Squeeze stable right now, and it has a manpage for ssft.sh. Try man ssft.sh. If that doesn't do what you want, let me know and you and I will figure out what does.
Update: All right. You have tried the manpage, which doesn't tell you what you want to know. There does not appear to exist any more thorough documentation for Ssft (maybe, when this is all over, you will write and contribute that very documentation). However, in Ssft's source appears to be a test script that makes the software do the various things it is designed to do. Sometimes, a good example is even better than a manual. That test script may be just what you need.
To extract the test script, issue a sequence of commands like the following sequence.
$ cd /tmp
$ apt-get source ssft
$ ls
$ cd ssft-0.9.13 # (Your version number may differ from 0.9.13.)
$ ls
$ cd tests
$ ls
When I do the above, the last ls listing reveals a shell script named ssft-test.sh. Inside that script appear to be several examples of how to use ssft.sh correctly.
http://man.devl.cz/man/1/ssft.sh
ssft.sh(1)
SSFT
Name
ssft.sh - library of shell script frontend functions
Synopsis
. ssft.sh
Description
ssft.sh is a library of shell functions that must be sourced from other scripts. If the script is executed without arguments it prints an usage message and also supports the options --doc, --help and --version.
To get a list of available functions call the script with the --doc argument and to get a description of what a given function does call the script with --doc FUNCTION_NAME.
On the typical case the library must be sourced and the SSFT_FRONTEND variable must be set to the desired frontend (zenity, dialog or text); if the variable is not set the default frontend is noninteractive.
To choose the theorically best looking frontend use the function ssft_choose_frontend as follows:
. ssft.sh [ -n "$SSFT_FRONTEND" ] || SSFT_FRONTEND="$( ssft_choose_frontend )"
Written by Sergio Talens-Oliag .
$ /usr/bin/ssft.sh
Shell Script Frontend Tool (version 0.9.13)
Usage: . ssft.sh
When called directly the program supports the following options:
-d,--doc [FUNCTIONS] Prints the list of available functions. If function names are given prints functions' documentation.
-h,--help This message
-v,--version File version
functions:
$ /usr/bin/ssft.sh -d
ssft_set_textdomain
ssft_reset_textdomain
ssft_choose_frontend
ssft_print_text_title
ssft_display_message
ssft_display_error
ssft_display_emsg
ssft_file_selection
ssft_directory_selection
ssft_progress_bar
ssft_read_string
ssft_read_password
ssft_select_multiple
ssft_select_single
ssft_yesno
ssft_show_file

Why ./script/generate is needed instead of script/generate in some Rails instruction?

Inside of Bash or Windows (or any other shell), is it needed to do
./script/generate scaffold foo name:string
instead of just using
script/generate ...
? I do see the first form sometimes, but the second form always works for me, on Mac OS X or Ubuntu, even if the PATH doesn't include the . (current directory)
So can the second form always work, so the first form is really not needed? I think for executable, we sometimes use ./a.out to run it... but seems like maybe script/generate doesn't need the ./ in front?
They mean exactly the same thing.
Starting from the current directory, select a subdirectory called 'script' and in it an executable called 'generate' and run it.
The difference is that with ./ you're explicitly specifying the current directory and without it, it's implicit.
There are 2 syntaxes of invocations in POSIX shell:
Running a program by specifying a name and then searching it in PATH enviornment variable - this one is used when program's name has no slashes (/).
Running a program by specifying full path to it manually - absolutely (path starting with /) or relatively (path starting with any other symbol). This one is chosen when program's name includes at least one / - thus it's a path, not just a name of file.
In your case, both ways to invoke - script/generate or ./script/generate are executed using variant #2 - by specifying a path to the program. ./ is an alias to current directory and in some cases it's required to be present (for example, when using cd command, you can't just say cd without argument and expect to change into current directory - cd reserves call without arguments to change to $HOME directory - but you may call cd ./ if you want to cd into current directory), but it's not required in this case of invocation.
you might want to have a look at 4 Ways of Executing a Shell Script and Shell Script Execution Guidlines. The main difference between both styles is:
script/generate ...
won't work if the parent directory of script does not lie in your current PATH environment. (Well this sure depends on how the shell's lookup method is implemented. There might be implementations that - to a last resort - are looking within your current working directory).
EDIT
Ok, I've done some research on this as I myself didn't seem to be knowing what the difference is. So, this is what I've arrived at:
The ./ (dot slash) syntax is an alias for the absolute path of the current working direcotry, so that - with e.g. /home/peter/script being the cwd -
peter#linux:/home/peter/script$./myscript
is expanded to /home/peter/script/myscript. The slash dot alias basically gives the shell a hint at where to find the executable/script.
That hint is what's essential, and that's the reason why
peter#linux:/home/peter$script/myscript
works as well whereas
peter#linux:/home/peter/script$myscript
won't. The former aids the shell in finding the right executable/script by providing some sort of reference point (namely the script directory). The latter, on the other hand, leaves the shell with a possibly ambiguous command, as there could be a homonymous script within the user's $PATH.
So, to come to an end, both of the styles you've asked the difference for do basically the same - giving the shell a hint at where to look for the executable/script. The shell then is able to unambiguously resolve the correct file and will happily execute it.
Have a nice day.
Nothing wrong with those answers except that they are too long - it's just about your PATH. If your path includes '.' then either way would workThat said, it's a bad habit to put '.' in your PATH for security reasons, so stick with './'

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