In Bash, how can I tell if I am currently in a terminal - bash

I want to create my own personal logfile that logs not only when I log in and out, but also when I lock/unlock my screen. Kindof like /var/log/wtmp on steroids.
To do this, I decided to run a script when I log into Ubuntu that runs in the background until I quit. My plan to do this is to add the script to .bashrc, using ./startlogging.sh & and in the script I will use trap to catch signals. That's great, except .bashrc gets run every time I open a new terminal, which is not what I want for the logger.
Is there a way to tell in Bash that the current login is a gnome login? Alternatively, is there some sort of .gnomerc I can use to run my script?
Edit: Here is my script:
Edit 2: Removed the script, since it's not related to the question. I will repost my other question, rather than repurpose this one.

Are you looking for a way to detect what type of terminal it is?
Try:
echo $TERM
From Wikipedia:
TERM (Unix-like) - specifies the type of computer terminal or terminal
emulator being used (e.g., vt100 or dumb).
See also: List of Terminal Emulators

for bash use : ~/.bash_logout
that will get executed when you logout, which sounds like what you are trying to do.

Well, for just bash, what you want are .bash_login/.bash_logout in your home directory (rather than .bashrc) These are run whenever a LOGIN shell starts/finishes, which happens any time you log in to a shell (on a tty or console, or via ssh or other network login). These are NOT run for bash processes created to run in terminal windows that you create (as those are not login shells) so won't get run any time you open a new terminal.
The problem is that if you log in with some mechanism that does not involve a terminal (such as gdm running on the console to start a gnome or kde or unity session), then there's no login shell so .bash_login/logout never get run. For that case, the easiest is probably to put something in your .xsessionrc, which will get run every time you start an X session (which happens for any of those GUI environments, regardless of which one you run). Unfortunately, there's no standard script that runs when an X session finishes.

Related

How to correctly emulate terminal in linux/macOS using exex(go)?

I need to emulate a terminal in go. I try to do it like this:
lsCmd := exec.Command("bash", "-c", "ls")
lsOut, err := lsCmd.Output()
if err != nil {
panic(err)
}
fmt.Println(string(lsOut))
And it seems to work correctly (the native ubuntu terminal displays a horizontal list, and the result of this function goes vertically).
But if I specifically call the wrong command, for example exec.Command ("bash", "-c", "lss"), I get:
panic: exit status 127
And in the native ubuntu terminal I get the following result:
Command 'lss' not found, did you mean:
and enumeration of commands.
I need to communicate with the native terminal, and get the same thing as the result of the command if I wrote the command in the standard ubuntu terminal.
What is the best way to do this? Maybe the exec library is not suitable for this? All this is necessary for front-end communication with the OS terminal. On a simple html/css/js page, the user enters a command, after go it sends it to the native terminal of the operating system and returns the result to the front-end.
How I can get the same result of executing commands as if I were working in a native terminal?
The problem
But if I specifically call the wrong command, for example exec.Command
("bash", "-c", "lss"), I get:
panic: exit status 127
And in the native ubuntu terminal I get the following result:
Command 'lss' not found, did you mean:
and enumeration of commands.
This has nothing to do with Go, and the problem is actually two-fold:
Ubuntu ships with a special package, command-not-found, which is usually preinstalled, which tries make terminal more friently for mere mortals by employing two techniques:
It tries to suggest corrections for misspellings (your case).
It tries to suggest packages to install when the user tries to execute a program which would have been be available if the user had a specific package installed.
When the command is not found, "plain" (see below) shell fails the attempt by returning a non-zero exit code.
This is absolutely expected and normal.
I mean, panicking on it is absolutely unwise.
There's a historical difference on how a shell is run on a Unix system.
When a user logs into the system (remember that back in the days the concept of the shell was invented you'd be logging in via a hardware computer terminal which was basically what your GNOME Terminal window is but in hardware, and connected over a wire),
the so-called login shell is started.
The primary idea of a logic shell is to provide interactive environment for the user.
But as you surely know, shells are also capable of executing scripts.
When a shell executes a script, it's running in a non-interactive mode.
The modes a Unix shell can work in
Now let's dig deeper into that thing about interactive vs non-interactive shells.
In the interactive mode:
The shell is usually connected to a real terminal (either hadrware or a terminal emulator; your GNOME Terminal window is a terminal emulator).
"Connected" means that the shell's standard I/O streams are connected to the terminal, so that what the shell prints is displayed by the terminal.
It enables certain bells and whistles for the user, usually providind limited means for editing what is being input (bash, for instance, engages GNU readline.
In the non-interactive mode:
The shell's standard I/O streams are connected to some files (or to "nowhere" — like /dev/null).
No bells and whistles are enabled — as there is nobody to make use of them.
GNU bash is able to run in both modes, and which mode it runs in depends
on how it was invoked.
When initializing in different modes, bash reads different initialization scripts, and this explains why the machinery provided by the command-not-found package gets engaged in the interactive mode and does not when bash is run otherwise — like in your invocation from Go.
What do do about the problem
The simplest thing to try is to run bash with the --login command-line option or otherwise make it think it runs as an interactive shell.
This might solve the problem for your case but not necessarily.
The next possible problem is that some programs do really check whether they're running at a terminal — usually these are programs which insist on real interaction with the user, usually for security purposes, and there are programs which simply cannot run when not connected to a real terminal — these are "full-screen" text UI programs such as GNU Midnight Commander, Vim, Emacs, GNU Nano and anything like this.
To solve this problem, the only solution is to run the shell in a pseudo-terminal environment, and that's what #eudore hinted at in their comment.
The github.com/creack/pty might be a package to start looking at; golang.org/x/crypto/ssh also provides some means to wrangle PTYs.

Bash shell is locked after running script

I made my own script to make testing a little faster to execute on my .NET projects.
The name of the script is TestCoverage and is located in /home/user/bin folder with executable permissions and also added to my PATH for convenience.
#!/bin/bash
echo "Collecting TestCoverage..."
dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
The script runs as expected but after it's done the terminal stops taking input. I can only press the Enter key and the cursor is blinking as usual.
Bash version 4.4.20 running on Ubuntu 18.04
I've made some testing and it seems to take input but it isn't showed to the console. The problem is not consistent, it comes and goes through different terminal sessions.
Your script (and likely the dotnet process it invokes, because echo is a shell intrinsic that usually returns within milliseconds) is probably still running and hasn't returned.
You can open another console and type ps aux -H to view the running processes - look out for some adjacent lines with TestCoverage, bash, and dotnet.
In those lines, you can see what state the process(es) are in
(RTM for further detail).
If you are running a console under X, you can first look around whether you accidentally pushed some running dotnet test ... window behind your console window. :-)

How to save a Python 2 idle/shell/command prompt interactive session on Windows?

I run calculations on Windows for hours and would like to have the calculation report/log inside the interactive IDLE/shell window be saved to a file at the end by a command.
Would be nice to exit() and close the window too.
As much as I like Linux, this is an Unattended Windows machine, hence, some modules/commands are not available, sadly, and the ability to install other software is limited.
The fact that the developers did not think of a command to save the transactions within the IDLE/shell is surprising.
I know in some environments you can direct the output of a job, like a report to another text file by using the key -o, --o, --output, > to a text file. Surprisingly Python does not support anything like that!
Any help would be appreciated
Thanks
Windows Command Prompt supports stdout redirection and probably stderr redirection. I just tested python -c "print(test)" > F:/dev/tem/out.txt and the print out went to out.txt. Replace -c "print('test') with script.py and the same should happen. Piping stdout of one program to stdin of another might work. You might be able to chain programs with a .bat file. PowerShell likely is more powerful and flexible, but I have never used it.
I am not completely clear on what you are asking, but I hope the following answers your questions.
Python runs in 2 modes: batch and interactive. Interactive mode is intended for ephermeral interaction with a human. Batch mode is for unattended computation, with occasional screen messages, but with most results sent to a file other than the screen. Both modes are combined when you run python -i xyz.py. The file is first run in batch mode, and then Python shifts to interactive mode.
It sounds like you should be using batch mode rather than either Python's or IDLE's interactive mode. If your code runs from IDLE, you should be able to run it directly with the same python.exe that you used to run IDLE. There are exceptions, of course, if one makes one's code dependent on running within IDLE, but this is unlikely to be an accident or to be needed for unattended running.
The IDLE Shell simulates interactive Python. When a file is run from an editor window, IDLE simulates python -i file-being-edited.py, with screen output going to Shell. In either case, an interactive user can save the contents of Shell with the File => Save As menu command. So there is such a command. There are also close window and exit commands and shortcuts.
In IDLE's intended use, as an interactive python learning and program development environment, there is no need from for a program to issue these commands. To save data in a file, a program can open a file and write data directly.
Try to see if you can install Jupyter Notebook (not separate software, but just a python module)
pip install jupyter
Jupyter notebook is highly helpful for saving and sharing your code. It can be used as both a shell and as a script editor.

Remove "Last login" message for new tabs in terminal

After some search about it I created a ~/.hushlogin file and it worked, but only for new windows. Is there a way to make it work for new tabs too?
On Mavericks, creating the empty file ~/.hushlogin removes the line “Last login”, for new windows and new tabs.
On my Mac it works.
Solution
This is running OS X 10.8.3. I haven't tested it on other versions, but so long as Terminal has the above option, then it should work.
In Terminal.app, go to Preferences->Settings and select the profile you're using. Go to the 'Shell' tab and under the 'Startup' heading, check 'Run command:' and enter into the box:
login -fpql your-username /bin/bash
Substitute your-username with your actual Unix username. If you use a shell other than the default bash shell, replace /bin/bash with the full path to that shell (yes, even if you've already set it in Preferences->Startup.)
Make sure 'Run inside shell' is unchecked.
If you have the "Prompt before closing: Only if there are processes other than login shell and:" option selected, add "login" and "bash" to the list of processes it will not prompt for.
Make sure you have a ~/.bashrc file, since this will be the file bash uses on startup from now on rather than ~/.bash_profile. I just have one file reference the other using this method. You also need to be sure it sources /etc/profile.
Explanation
We want to run login with the -q option to tell it to supress the "Last login" message, even in the absence of a .hushlogin file. (As noted above, login will only look in cwd for that file, not your home directory, so you'd need a .hushlogin file in every directory you'd open a shell to, for that method to work.)
The problem is Terminal runs something like login -pfl your-username /bin/bash -c exec -la bash /usr/local/bin/bash when you create a new shell (I'm using homebrew's version of bash, hence the weird bash path at the end,) which lacks the -q flag.
Unfortunately, there's no way to directly change the arguments Terminal uses, so we just trampoline a new login session with login -pfql from Terminal's default login -pfl session. Inelegant, but it works.
We need to have the -q option and the path to bash to keep the "New windows/tabs open with: Same Working Directory" option working. If you don't care about that option, you can remove that flag and argument, and probably avoid the .bashrc stuff above.
you could just add a clear to your .bash_profile
Adding ~/.hushlogin is fine unless you want to open a new tab in the same folder, or open Terminal from Finder on the exact folder, in that case it won't work.
Changing a running command to another login is something I would like to avoid because of the strange unnecessary scheme login -> login -> zsh. You can see it in Activity Monitor, but also it will show up when you are quitting interactive programs (like, python repl) in the message that python, login and zsh are running.
Putting clear in ~/.zshrc is not ideal since on mac it just prints a lot of newlines (and if you scroll back, you'll see them).
The best way that I found up to this point is adding printf '\33c\e[3J' to ~/.zshrc (or in Terminal/Preferences/Profiles/Shell/Startup/Run command with Run inside shell checked). I chose beginning of ~/.zshrc file since startup command is running after it and if the ~/.zshrc file is heavy you can briefly see Last Login message before printf is executed.
This might be OS version dependent. On Terminal 2.3 (on 10.8), touching the file ~/.hushlogin suppresses the 'last login' message for new tabs as well as new windows. That is, it Works For Me.
Just in case it helps to work out what's going on (and in case you don't know), note that the 'last login' message is in principle coming from login(1), and not the shell. Or, more precisely, if a shell is invoked in a particular way (including starting it with the -l option), then bash will "act as if it had been invoked as a login shell" (zsh may have a similar feature, though I can't find it right now). Now, it could be that when Terminanl opens up a new tab in your OS X version, the shell is effectively simulating opening a login shell, and maybe getting this detail wrong. But if you have the 10.8 version of bash/zsh (namely 3.2.48 / 4.3.11), then I don't know what might be amiss.
A simple solution without changing anything related to login would be just to add the clear command in the end of your ~/.bashrc or ~/.zshrc file. It will clear the terminal in initialization from any initialization prints. It works for me very well.
On my MacOS Big Sur 11.1 it works.

Running a command as a background process/service

I have a Shell command that I'd like to run in the background and I've read that this can be done by suffixing an & to the command which causes it to run as a background process but I need some more functionality and was wondering how to go about it:
I'd like the command to start and run in the background every time the system restarts.
I'd like to be able to able to start and stop it as and when needed just like one can do service apache2 start.
How can I go about this? Is there a tool that allows me to run a command as a service?
I'm a little lost with this.
Thanks
UNIX systems can handle as many processes as you need simultaneously (just open new shell windows if you're in a GUI), so running a process in the background is only necessary if you need to carry on using the current shell window for other things once you've run an application or process that keeps running.
To run a command called command in background mode, you'd use:
command &
This is a special character that returns you to the command prompt once the process is started. There are other special characters that do other things, more info is available here.
Take a look at the daemon command, which can turn arbitrary processes into daemons. This will allow your script to act as a daemon without requiring you to do a lot of extra work. The next step is to invoke it automatically at boot. To know the correct way to do that, you'll need to provide your OS (or, for Linux, your distribution).
Based on this article:
http:// felixmilea.com/2014/12/running-bash-commands-background-properly/
...another good way is with screen eg:
screen -d -m -s "my session name" <command to run>
from the screen manual:
-d -m
Start screen in detached mode. This creates a new session but doesn't attach to it. This is useful for system startup scripts.
i.e. you can close your terminal, the process will continue running (unlike with &)
with screen you can also reattach to the session later
Use nohup while directing the output to /dev/null
nohup command &>/dev/null &
For advanced job control with bash, you should look into the commands jobs bg and fg.
However, it seems like you're not really interested in running the command in the background. What you want to do is launch the command at startup. The way to do this varies depending on the Unix system you use, but try to look into the rc family of files (/etc/rc.local for example on Ubuntu). They contain scripts that will be executed after the init script.

Resources