How can I get the window ID of the terminal that my shell script is running in?
Background:
I need to write a script to do something based on which virtual desktop it is running in. To get the virtual desktop (not current desktop, I may change it while the script is running), I need the window ID of the terminal that the script is running in. If the script is not run from a terminal, it should fail with an error.
I know very little of X11, but running the env command in my terminal, I spotted an environment variable WINDOWID, that shows the same number in different tabs of the same terminal, but a different number in another terminal. Perhaps that's what you need?
It does appear to be an Xterm thing (and probably any terminal that mimicks Xterms behaviour. The xterm(1) man page only says:
ENVIRONMENT
Xterm sets several environment variables:
...
WINDOWID
is set to the X window id number of the xterm window.
Some other possibly relevant questions with answers:
https://unix.stackexchange.com/questions/3197/how-to-identify-which-xterm-a-shell-or-process-is-running-in
Get X window id from process in bash
Related
Is there a means to determine whether the zsh shell is currently executing (any) process? I'd like to bind a key only when the terminal prompt is not available (i.e. a process is currently executing within it so the user cannot execute new commands). This is for accessibility purposes.
So, for example, if I have a blank prompt:
zork#macbook $, pressing x does nothing.
But if I have a long running process like a dev server:
zork#macbook $ serve localhost:3000
I could bind the key x to ctrl+C.
Is there any way to accomplish this?
When you run serve localhost:3000, serve becomes the foreground process with which your terminal interacts, instead of the Zsh line editor (ZLE). So, at this point, the ZLE can no longer handle your keybindings. Instead, you will have to process the keystrokes inside serve.
Let's say I'm running xterm or some other terminal emulator on top of some graphical X Window Environment. xterm on KDE, for example. I want to write an application that may be called on the command line of one terminal emulator, and upon execution, the application creates a new KDE/Environment window, separate from the current terminal emulator, and on that new window run an Ncurses context for application purposes.
How would I do this? Is this terminal emulator dependent? Desktop environment dependent? Would I be using bare X window system calls?
It's terminal (emulator) dependent.
Curses runs in terminals and terminal emulators. Most of the latter (terminal emulators) have some way to tell what program (other than your shell) to run in the terminal emulator.
For instance, xterm can be told using the -e option,
-e program [ arguments ... ]
This option specifies the program (and its command line
arguments) to be run in the xterm window. It also sets the
window title and icon name to be the basename of the program
being executed if neither -T nor -n are given on the command
line.
NOTE: This must be the last option on the command line.
letting you start an xterm running MyApplication like this:
xterm -e MyApplication
Again, most of the terminal emulators you might run in X accept that option. KDE konsole does that. There's no manual, but
konsole --help-all
shows it at the end.
I have a GUI macOS app that may also be launched from Terminal, with optional command line arguments.
When launched with arguments, I like to run the app in a "cmdline" mode where I do not display any UI but instead communicate via stdin + stdout only.
I can detect this cmdline mode like this:
BOOL cmdMode = NSProcessInfo.processInfo.arguments.count > 1;
(arg 0 is always the executable's path, so any more args would be manually passed args).
Now, here's the big question:
If the user invokes my app without arguments from Terminal (by invoking the app's executable in Contents/MacOS, i.e. not via the open cmd), I like to also go into the cmdline mode. How do I detect this?
Note: Older OS X versions did pass a "-psn ..." argument that, when not present, could be used to detect a launch from cmdline, but recent macOS versions seem to not pass this argument any more when launching apps from the Finder, so I cannot use that for detection any more.
Update
I realize that I can almost correctly solve this by checking for the presence of certain environment variables:
TERM and PWD are only set when launching the app from Terminal but not from Finder.
However, I also like to be able to tell the difference between being launched directly (executable in Contents/MacOS dir) vs. launched with the open command as I consider the open cmd being equivalent to opening the app via Finder or from another app via Launch Services.
In short, the question might also be: Detect whether an app was launched by Launch Services
For the record, here are the values from environ(). The ones marked with an asterisk are only present when invoked from Terminal.app but not when lanched from Finder:
__CF_USER_TEXT_ENCODING=0x1F5:0x0:0x0
* _=/Applications/Myapp.app/Contents/MacOS/Myapp
Apple_PubSub_Socket_Render=/private/tmp/com.apple.launchd.laVQnD7IXl/Render
HOME=/Users/username
* LANG=en_US.UTF-8
* LC_ALL=en_US.UTF-8
* LC_CTYPE=UTF-8
LOGNAME=username
PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
* PWD=/Users/username
SHELL=/bin/bash
* SHLVL=1
SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.KeHv8KNuuk/Listeners
* TERM_PROGRAM_VERSION=388.1.2
* TERM_PROGRAM=Apple_Terminal
* TERM_SESSION_ID=EF2C59E6-D661-45BE-B7EF-7A0E71158C8D
* TERM=xterm-color
TMPDIR=/var/folders/hm/ycnxcbwx8xl1v7008k8wnpjh0000gn/T/
USER=username
XPC_FLAGS=0x0
XPC_SERVICE_NAME=0
There are, however, no envinment values that are unique to apps launched with Launch Services (such as when double clicked in Finder).
If you want to know what process has executed your program, you could use getppid() to get the parent process ID, then inspect that process to determine whether you were executed by an interactive shell process, or Finder, or launchctl, etc.
/sbin/launchd is PID 1 - if your process's parent PID is 1, you were executed by launchd.
Otherwise, you were executed by another process - probably an interactive shell, or as a subprocess of another process. You can use the KERN_PROCARGS syscall with sysctl() to get the process name by its PID.
You might also want to consider using isatty(STDIN) as well: interactive shells have a TTY, non-interactive shells and other processes won't.
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.
I'm writing a ksh script and I have to run a executable at a separate Command Prompt window.
xdg-open is a similar command line app in linux.
see https://superuser.com/questions/38984/linux-equivalent-command-for-open-command-on-mac-windows for details on its use.
I believe you mean something like xterm -e your.sh &
Don't forget the final &
maybe it´s not a seperate window that gets started, but you can run some executables in background using "&"
e.g.
./myexecutable &
means your script will not wait until myexecutable has finished but goes on immediately. maybe this is what you are looking for.
regards
xdg-open is a good equivalent for the MS windows commandline start command:
xdg-open file
opens that file or url with its default application
xdg-open .
opens the currect folder in the default file manager
One of the most useful terminal session programs is screen.
screen -dmS title executable
You can list all your screen sessions by running
screen -ls
And you can connect to your created screen session (also allowing multiple simultaneous/synchronized sessions) by running
screen -x title
This will open up the emulated terminal in the current window where executable is running. You can detach a screen session by pressing C-a C-d, and can reattach as many times as you wish.
If you really want your program started in a new terminal window, you could do something like this:
xterm yourtextmodeprogram
or
gnome-terminal -e yourtextmodeprogram
or
konsole -e mc
Trouble is that you cannot count on a particular terminal emulator being installed, so (again: if you really want to do this) you would need to look for the common ones and then execute the first one encountered.
As Joachim mentioned: The normal way to do this is to background the command (read about shell job control somewhere, if you want to dig deeper).
There are also cases where you want to start a persistent shell, i.e. a shell session which lives on when you close the terminal window. There are two ways to do this:
batch-oriented: nohup command-to-run &
interactive: screen
if you want a new windows, just start a new instance of your terminal application: in kde it's
konsole -e whatever
i'm sure the Gnome terminal has similar options
Some have recommended starting it in the background with &, but beware that that will still send all console output from the application you launch to the terminal you launched it from. Additionally, if you close the initial terminal the program you loaded will end.
If you're using a desktop environment like KDE or GNOME, I'd check the alt+f2 launching apps (gnome-open is the one for GNOME, I don't know the name of the KDE app) and see if you can pass them the command to launch as an argument.
Also, if your intention is to launch a daemon, you should check the nohup documentation.
I used nohup as the following command and it works:
nohup <your command> &
then press enter and enter!
don't forget the last &
for example, I ran a python code listening to port 5000:
nohup python3 -W ignore mycode.py &
then I made sure of running by netstat -tulnp | grep :5000 and it was ok.