Difference between linux variables $BASH_SUBSHELL vs $SHLVL
No, manually running a new shell (via /bin/sh
or /bin/bash
etc.) is not a subshell in this context.
A subshell is when the shell spawns a new shell instance on its own to handle some work.
Using Command Substitution (i.e. $(command)
) is a subshell (as is the older backticks invocation).
Using a pipeline (i.e. echo '5.1+5.3' | bc -l
) creates subshells for each component of the pipeline.
Using Process Substitution (i.e. <(command)
) creates a subshell.
Grouping commands (i.e. (declare a=5; echo $a)
) creates a subshell.
Running commands in the background (i.e. sleep 1 &
) creates a subshell.
There may be other things as well but those are the common cases.
Testing this is easy:
$ printf "Outside: $BASH_SUBSHELL , $SHLVL\nInside: $(echo $BASH_SUBSHELL , $SHLVL)\n"
Outside: 0 , 1
Inside: 1 , 1
$ (printf "Outside: $BASH_SUBSHELL , $SHLVL\nInside: $(echo $BASH_SUBSHELL , $SHLVL)\n")
Outside: 1 , 1
Inside: 2 , 1
$ bash -c 'printf "Outside: $BASH_SUBSHELL , $SHLVL\nInside: $(echo $BASH_SUBSHELL , $SHLVL)\n"'
Outside: 0 , 2
Inside: 1 , 2
$ bash -c '(printf "Outside: $BASH_SUBSHELL , $SHLVL\nInside: $(echo $BASH_SUBSHELL , $SHLVL)\n")'
Outside: 1 , 2
Inside: 2 , 2
The source of your quote (the generally poor, and often better avoided, ABS) even demonstrates this a little bit (and in a rather unclear manner, just another instance of the general lack of rigor and quality in that "Advanced" guide):
echo " \$BASH_SUBSHELL outside subshell = $BASH_SUBSHELL" # 0
( echo " \$BASH_SUBSHELL inside subshell = $BASH_SUBSHELL" ) # 1
( ( echo " \$BASH_SUBSHELL inside nested subshell = $BASH_SUBSHELL" ) ) # 2
# ^ ^ *** nested *** ^ ^
echo
echo " \$SHLVL outside subshell = $SHLVL" # 3
( echo " \$SHLVL inside subshell = $SHLVL" ) # 3 (No change!)
$SHLVL does not increase in ( echo $SHLVL)
You actually need to use $BASH_SUBSHELL
instead of $SHLVL
here.
$BASH_SUBSHELL
is an internal variable that indicates the nesting level of a subshell.
Change your script to this:
#!/usr/bin/env bash
A=1
(A=2;echo "A is $A in $BASH_SUBSHELL:$SHLVL")
echo "A is $A in $BASH_SUBSHELL:$SHLVL"
Now it will output:
A is 2 in 1:2
A is 1 in 0:2
You can see $BASH_SUBSHELL
changes with the nesting level but $SHLVL
remains same.
Check this helpful answer for more details
How JavaScript does OOP?
In your example you are not creating an instance of a Person class. You are creating a variable named 'Person' which contains an anonymous object.
To create a class of type Person you would do:
function Person() {
this.name = "John Doe",
this.sayHi = function() {
alert("Hi");
}
}
var somebody = new Person();
Otherwise I think that your question is too broad and complex. There are many javascript articles and tutorials on the web (and books in the bookstores). Go and study them and if you don't understand something specific then post here.
Determining whether shell script was executed sourcing it
I think, what Sam wants to do may be not possible.
To what degree a half-baken workaround is possible, depends on...
- ...the default shell of users, and
- ...which alternative shells they are allowed to use.
If I understand Sam's requirement correctly, he wants to have a 'script',myscript
, that is...
- ...not directly executable via invoking it by its name
myscript
(i.e. that haschmod a-x
); - ...not indirectly executable for users by invoking
sh myscript
or
invokingbash myscript
- ...only running its contained functions and commands if invoked by
sourcing it:. myscript
The first things to consider are these
- Invoking a script directly by its name (
myscript
) requires a first line in
the script like#!/bin/bash
or similar. This will directly determine which
installed instance of the bash executable (or symlink) will be invoked to run
the script's content. This will be a new shell process. It requires the
scriptfile itself to have the executable flag set. - Running a script by invoking a shell binary with the script's (path+)name as
an argument (sh myscript
), is the same as '1.' -- except that the
executable flag does not need to be set, and said first line with the
hashbang isn't required either. The only thing needed is that the invoking
user needs read access to the scriptfile. - Invoking a script by sourcing its filename (
. myscript
) is very much the
same as '1.' -- exept that it isn't a new shell that is invoked. All the
script's commands are executed in the current shell, using its environment
(and also "polluting" its environment with any (new) variables it may set or
change. (Usually this is a very dangerous thing to do: but here it could be
used to executeexit $RETURNVALUE
under certain conditions....)
For '1.':
Easy to achieve: chmod a-x myscript
will prevent myscript
from being
directly executable. But this will not fullfill requirements '2.' and '3.'.
For '2.' and '3.':
Much harder to achieve. Invokations by sh myscript
require reading
privileges for the file. So an obvious way out would seem to chmod a-r
. However, this will also dis-allow '3.': you will not be able to
myscript
source the script either.
So what about writting the script in a way that uses a Bashism? A Bashism is a
specific way to do something which other shells do not understand: using
specific variables, commands etc. This could be used inside the script to
discover this condition and "do something" about it (like "display warning.txt",
"mailto admin" etc.). But there is no way in hell that this will prevent sh
orbash
or any other shell from reading and trying to execute all the following
commands/lines written into the script unless you kill the shell by invokingexit
.
Examples: in Bash, the environment seen by the script knows of $BASH
,$BASH_ARGV
, $BASH_COMMAND
, $BASH_SUBSHELL
, BASH_EXECUTION_STRING
... . If
invoked by sh
(also if sourced inside a sh
), the executing shell will see
all these $BASH_*
as empty environment variables. Again, this could be used
inside the script to discover this condition and "do something"... but not
prevent the following commands from being invoked!
I'm now assuming that...
- ...the script is using
#!/bin/bash
as its first line, - ...users have set Bash as their shell and are invoking commands in the
following table from Bash and it is their login shell, - ...
sh
is available and it is a symlink tobash
ordash
.
This will mean the following invokations are possible, with the listed values
for environment variables
vars+invok's | ./scriptname | sh scriptname | bash scriptname | . scriptname
---------------+--------------+---------------+-----------------+-------------
$0 | ./scriptname | ./scriptname | ./scriptname | -bash
$SHLVL | 2 | 1 | 2 | 1
$SHELLOPTS | braceexpand: | (empty) | braceexpand:.. | braceexpand:
$BASH | /bin/bash | (empty) | /bin/bash | /bin/bash
$BASH_ARGV | (empty) | (empty) | (empty) | scriptname
$BASH_SUBSHELL | 0 | (empty) | 0 | 0
$SHELL | /bin/bash | /bin/bash | /bin/bash | /bin/bash
$OPTARG | (empty) | (empty) | (emtpy) | (emtpy)
Now you could put a logic into your text script:
- If
$0
is not equal to-bash
, then do anexit $SOMERETURNVALUE
.
In case the script was called via sh myscript
or bash myscript
, then it will
exit the calling shell. In case it was run in the current shell, it will
continue to run. (Warning: in case the script has any other exit
statements,
your current shell will be 'killed'...)
So put into your non-executable myscript.txt
near its beginning something like
this may do something close to your goal:
echo BASH=$BASH
test x${BASH} = x/bin/bash && echo "$? : FINE.... You're using 'bash ...'"
test x${BASH} = x/bin/bash || echo "$? : RATS !!! -- You're not using BASH and I will kick you out!"
test x${BASH} = x/bin/bash || exit 42
test x"${0}" = x"-bash" && echo "$? : FINE.... You've sourced me, and I'm your login shell."
test x"${0}" = x"-bash" || echo "$? : RATS !!! -- You've not sourced me (or I'm not your bash login shell) and I will kick you out!"
test x"${0}" = x"-bash" || exit 33
How JavaScript does OOP?
In your example you are not creating an instance of a Person class. You are creating a variable named 'Person' which contains an anonymous object.
To create a class of type Person you would do:
function Person() {
this.name = "John Doe",
this.sayHi = function() {
alert("Hi");
}
}
var somebody = new Person();
Otherwise I think that your question is too broad and complex. There are many javascript articles and tutorials on the web (and books in the bookstores). Go and study them and if you don't understand something specific then post here.
Related Topics
Make Bash Differentiate Between Ctrl-<Letter> and Ctrl-Shift-<Letter>
Git Post-Receive Checkout to Remote Machine
Ubuntu/Fedora: How to Add Applications in The Menus
Linux/Unix Socket Self-Connection
Linux: Update Embedded Resource from Executable
How to Launch Linux Subshell for Ssh_Askpass to Work in Linux
List of Files Modified 1 Hour Before
What Are The Lowest Possible Permissions for Typo3
Installing Ffmpeg on Amazon Linux - Cpp, Gcc & Libstdc++ Dependancies
Need Explanation on Pri Standard Format Specifier for Ps - Possible Bug in Documentation
How to Log from a Non-Root Debian Linux Daemon
Initramfs Built into Custom Linux Kernel Is Not Running
Jenkins Running at Very High CPU Usage