Change current working directory of bash terminal with Nodejs - node.js

I want to develop a Node CLI app which clones a git repo and cd's into it.
For eg.
dummyuser:~$ dummy-cli-command dummy-git-repo-url
Cloning repository...
dummyuser:~/Workspace/dummy-git-repo$
I was able to clone it but am not able to cd into it. I know that node forks a child process under which it executes my code and there is no way to change directory of the bash terminal through which I first executed my node-cli-command. Can anyone help me with any workaround ?

You will not be able to do that - not with Node and not with any other program. You cannot even do it with a shell script, though you can do it with a shell alias or function but only if it is not run as a subprocess.
What it means is that you may be able to achieve that if your Node program returns the correct directory to a shell alias or shell function that runs it, and it's the alias or function that does the directory changing. That alias or function could know the destination in the first place if it gets it by command line arguments. But then again, if you use a shell function then you don't need Node to clone the repo in the first place.
The bottom line is that you will not be able to change the working directory of your shell from a subprocess so your only options are the ways to do it by running code in the same process like an alias or a function in the shell.

Related

#reboot crontab has no effect

I have this crontab #reboot "/home/pi/Desktop/TV Scraper 2.0/run.sh" set up and for whatever reason it doesn't seem to run the bash file on reboot.
Typing "/home/pi/Desktop/TV Scraper 2.0/run.sh" on the terminal actually runs the script, so I know it's correct.
This is what's inside run.sh just in case:
#!/bin/bash
cd "/home/pi/Desktop/TV Scraper 2.0"
node ./app.js
I've also tried using #reboot root sh "/home/pi/Desktop/TV Scraper 2.0/run.sh" as well, but it doesn't work either.
How can I move forward with this? My knowledge of Linux is very limited. All I need is to have some Node and Python3 scripts run on every reboot. On Windows that's such an easy task: I've tried CRON, rc.local and autostart, nothing works.
My guess is that node is not available via cronjob, since its containing directory is not in your PATH environment variable. When you execute the script manually, it's probably available via PATH.
An easy fix for this is to use the full path, which you can get by executing which node. The result should be something like /usr/bin/node. Then you can use that, instead of just node.
For debugging purpose you can also redirect stdout and stderr to a file, so the last line in your script would look like this:
/usr/bin/node ./app.js &>/tmp/cron-debug.log
If that doesn't fix it, i would rename the directory "TV Scraper 2.0" and replace the whitespace characters with something like an underscore. Directory and file names are less likely to cause problems if you avoid whitespaces.

How node script can run in my current bash context (process)?

In bash You can source or . to run some bash script in your current context. So if you have e.g. file foo with alias bar='echo bam' in it and when You run it like
$ . foo
it will source this alias from file foo into your current context.
I know if I normally run node script with first line like #!/usr/bin/env node then this script is run in sub-shell or as separate process. I want to avoid this and make node script act on my current bash process (context).
How can I run node script that alter my current bash context?
ps: Any example is good. Node script can only change my directory but again it must happen in my current bash context.
ps2: Sub question: If it's impossible in node (and it's very hard for me to believe in this) or it's very complicated then is it possible in other language? Like PHP, Java, Ruby (I don't ask for C because it's obvious :) and if so please give me some example.
I've struggled with this same problem when writing my Node implementation of wd. AFAIK there is no way to do what you want to do for reasons already known to you. However, if you want to use node in a sourced shell script, there is a way around it, kind of.
So you can't source a node script, but what you can do is execute node scripts in a sourced shell script. Performance isn't great, but it works. For example, you can't put process.chdir('/tmp'); in a node script and expect it to change the current working directory in your current process. But what you can do is make a node script that console.logs a directory and execute that in a sourced shell script with something like cd $(node myscript.js). For an example of this, check out the code in my project I linked above. There I use a bash function to source a shell script of a globally installed npm module which then executes JS to change the current dir (at least, in bash and zsh). It's not exactly pretty, but it works.
I know it's not the answer you were looking for, but it's as close as I've found a way to use node to manipulate the current bash context. I actually found this question because I was just trying to refactor and look for a better way to do this.. If I ever do find that better way I'll let you know ;-)

Linux basics - automating a script execution

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"

How to change directory through a script file

i want to execute some commands through terminal. I have on script for executing commands.Some commands are working but when trying to change directory its not changing. There is no error while executing that script.The script which i made is executable and is mention below:
make clean
make
cd /home/user
save this as script.sh and make it executable
Current working directory is a process property. Each process has independent value for its working directory. Your script works correctly: it changes the current working directory of the shell process that executes it.
If you want your interactive shell to change working directory you have to instruct it. You can do it by "sourcing" your script into your interactive shell. "Sourcing" means reading the script and executing the commands by the shell that sources it. This is opposed to "executing" the script, where a separate shell process is started and executes the script contents.
You can source a script using source or . commands. Like this:
source script.sh
or this:
. script.sh

shell export variable not come into effect

I (on mac osx) often use
export http_proxy=http://192.168.0.205:1099
to proxy http connection to get a highed download speed. To make things easy, I wrote a shell file named proxy.sh to do this:
#!/bin/sh
export http_proxy=http://192.168.0.205:1099
Before I downlaod, I execute proxy.sh shell command, but I found it did't not come into effect.It lost http_proxy variable in current commnad window(terminal). I must type export command in current terminal,it will come into effect.
So I want to know what's reason for this and a solution? thanks.
Running a shell script "normally" (with proxy.sh for example) results in that running in a sub-process so that it cannot affect the environment of the parent process.
Using . or source will run the shell script in the context of the current shell, so it will be able to affect the environment, using one of the following:
. proxy.sh
source proxy.sh
Another possibility (if you're using bash at least) is to create an alias to do the work for you. You can use something like:
alias faster='export http_proxy=http://192.168.0.205:1099'
so that you can then simply type faster on the command line and it will export that variable (in the context of the current shell).
You could also allow for one-shot settings such as:
alias faster='http_proxy=http://192.168.0.205:1099'
and then use:
faster your_program
which would translate into:
http_proxy=http://192.168.0.205:1099 your_program
That's a bash way to set a variable for just the one invocation of a command.
The export variable will only apply to the script -- if you want it to apply to the shell, you need to use source, and execute the script like so:
. ./proxy.sh
or:
source ./proxy.sh
Note the "." in the first example -- the dot follow by space means the script will apply to the shell.
The reason why your script does not work has been explained by Drakosha & how to make your script work has been explained by Anothony. But with the export in the script you need to source your script each time you open a new terminal. A better solution will be to add the export in .bash_profile or .bashrc
Hope this helps!
When executing a shell script a new shell is launched, the script is executed, and the shell dies. That's why you don't see the variable defined in your shell.
I suggest using an alias for the same purpose.

Resources