Opening Cygwin X11 applications in Windows 10 from desktop shortcuts - bash

I have 64-bit Cygwin installed on Windows 10, and I would like to open Cygwin GUI applications such as atril from desktop shortcuts, without having to open a Cygwin terminal and launching them from the command line manually.
I have:
created a ~/.startxwinrc file containing the line "exec sleep infinity"
added these lines to ~/.bashrc
export DISPLAY=:0.0
which startxwin > /dev/null 2>&1
if [ $? -eq 0 ]; then
startxwin > /dev/null 2>&1 &
fi
I can now open the applications by launching a Cygwin terminal, typing the name of the application, and pressing Enter. However, the desktop shortcuts I have created silently fail. One of these was:
C:\cygwin64\bin\run.exe -p /bin xterm -display 0.0 -e /bin/bash -l /cygdrive/c/Users/MYNAME/atril-launcher.sh
(I think that one failed because xterm and startxwin are incompatible; I may be wrong.)
I have tried other command lines which include run.exe, but have been unable either to launch the application or to get a meaningful error message.
atril-launcher.sh has the correct permissions, and contains the following text after the shebang (I couldn't get the formatting right trying to post the shebang in here.). It can be successfully launched from within the Cygwin terminal.
nohup /bin/atril.exe &
sleep 3s
I have searched the Internet for information on this problem, much of which is out of date (Cygwin now using /bin instead of /usr/bin, Cygwin no longer having an X11R6 folder, DISPLAY=:0.0 instead of DISPLAY=localhost:0.0, etc...) but at this point I'm at my wits' end.

It looks as though I've found a partial answer to my own question. It's imperfect for various reasons:
It probably depends on startxwin already having been launched elsewhere as a background process.
The applications are slow to launch; there's a delay of a few seconds.
Terminal windows which the user cannot interact with (presumably the shells which act as parent process for the GUI applications) appear alongside the application windows.
But it will probably be enough to be getting on with. Assuming pluma to be our application, here is the shortcut that successfully launches it:
C:\cygwin64\bin\mintty.exe /bin/bash -l -c "export DISPLAY=:0.0; pluma"
I'd like to thank the author of answer https://stackoverflow.com/a/12215570/9223868 - which I did not find through googling, only through its appearing in the "Related" list when this was posted.

Related

Why does Fastscripts work with this but Platypus doesn't

Mac running Catalina. This code
#!/bin/bash
pbpaste|pbcopy
pbpaste>/tmp/tmp$$
open -W -a macvim /tmp/tmp$$
while [ `ps -A|grep MacVim|wc -l` -gt 1 ]
do sleep 1
done
cat /tmp/tmp$$|pbcopy
rm -f /tmp/tmp$$
is intended to plain-text the paste buffer then call up a terminal running macvim so I can use vi with less faff then put the result back in the clipboard. Its a way to speed-up editing when using various tools other tools and I just want to edit a section with vi.
I works well when called from Fastscripts or just plain execution but it won't work when I use Platypus to build a menubar app so its one fast click to use it - or rather, it works sometimes. Sometimes it hangs because it cannot connect input to the window in which macvim runs. I have to kill it from Activity Monitor to regain any control of input to other windows such as terminal. I've tried connecting stdin in the "open" command but still only works sometimes. And it shouldn't be standin anyway.
How is Fastscripts launching it and how can I do the same inside the script ?
I'd like very much to be able to launch it with a single click from the menubar but I don't know how to. I can build the platypus app if I know what to put in the shell script.
Thanks
andy

How to elegantly create a Windows shortcut that starts a WSL program under X

I'm struggling a little to launch xfce4-terminal from my WSL installation under VcXsrv from a button on the Windows taskbar. I don't want any DOS box/console/terminal other than the xfce4-terminal when I'm done. I have it working, but man is it ugly. Does anybody have a cleaner way of doing this?
Here is what I got working: I created a windows shortcut on the Desktop with this target (all in one line, broken with newlines for readability here):
C:\Windows\System32\wscript.exe
\\wsl$\Ubuntu-20.04\home\peter\bin\windows\startTerminal.vbs
startTerminal.vbs was inspired by from 10 Ways To Run Batch Files Silently And Hide The Console Window • Raymond.CC (one of the few solutions that didn't require installing a separate program for this!) and it contains:
CreateObject("Wscript.Shell").Run "C:\Windows\System32\wsl.exe -u peter --exec /home/peter/bin/windows/startTerminal.sh",0,True
and startTerminal.sh contains:
export DISPLAY=localhost:0.0
xfce4-terminal --command=/bin/zsh
Setting DISPLAY is apparently required, even though I set the DISPLAY environment in ~/.zshrc. wsl.exe apparently doesn't do that unless you run the login shell.
Once all of this is working, I can drag my shortcut to the taskbar and click on it there.
I count 3, three files cooperating to achieve this simple goal? Can I limit that to one or two without installing an external program?
Yes, I think you can do what I do in one shortcut file. I'll share what works for me then you'll have to fiddle for your program.
Try putting all your commands in the Target section of the Shortcut link file.
Step 1. Right click on desktop then New then Shortcut then name it (LaunchXFCE4)
Step 2. Right click LaunchXFCE4 select Properties
Step 3. Enter all your launch sequences in the Target section
Step 4. Right click LaunchXFCE4 select Pin to Taskbar
I'm launching Emacs 27.1 on WSL 2 with Ubuntu 20.10 on Windows 10 using this code which perhaps you can modify.
C:\Windows\System32\wsl.exe --distribution Ubuntu20 bash -c "export DISPLAY=$(ip route | awk '{print $3; exit}'):0 && export LIBGL_ALWAYS_INDIRECT=1 && export XCURSOR_SIZE=16 && setsid emacs"
The first export display is similar to your localhost:0.0 so replace it or try mine. Maybe your xfce4 replaces my emacs. Read this post about double ampersands. So possibly this
C:\Windows\System32\wsl.exe --distribution Ubuntu20 bash -c "export DISPLAY=localhost:0.0 && export LIBGL_ALWAYS_INDIRECT=1 && export XCURSOR_SIZE=16 && setsid xfce4-terminal --command=/bin/zsh"
Note, my VcXsrv starts when windows starts by putting a shortcut to config.xlaunch in my C:\Users\USERNAME\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup.
By the way, Microsoft will provide a GUI for WSL in a few months, according to their blog
GUI app support in WSL is becoming a reality! We are getting closer to
an initial preview and happy to announce a preview release for Windows
Insiders within the next couple of months.
I removed the need for a startTerminal.sh file by:
Editing startTerminal.vbs to contain:
CreateObject("Wscript.Shell").Run "C:\Windows\System32\wsl.exe -u peter bash -l -c xfce4-terminal",0,True
And then I created a ~/.bash_profile to set the $DISPLAY variable, which probably should've been done anyway:
$ cat .bash_profile
if [ -z "$DISPLAY" ]; then
export DISPLAY=:0
fi
So now there is the shortcut and a startTerminal.vbs that starts it up. It still isn't very elegant...
One of the few good additions to Windows was WSL-2, it's much more capable now.
It's part of late Win 10 and Win 11.
Here is how to elegently create a terminal window, replace the terminal with any X app you want.
Linux: "apt-get install xfce4-terminal" (or equivalent)
Windows: Create a new Shortcut (right click in any windows folder)
2.1) Shortcut to -> C:\Windows\System32\wslg.exe -u root -- /usr/bin/xfce4-terminal
If you have multiple distributions use it like: "-d Debian"
That's it. You can give it a better icon and name it.
It will launch the application as if it was a windows application.
After experimenting with #Saj 's answer which did not work for me I resulted in the below:
C:\Windows\System32\wsl.exe --distribution Ubuntu-20.04 bash -c "export DISPLAY=$((route.exe print | Select-String 0.0.0.0 | select -first 1) -Split "\s+" | select -Index 4):0.0 && export LIBGL_ALWAYS_INDIRECT=1 && setsid emacs"
Note that my problem was that it could not use bash commands inside the parenthesis (grep, awk)
Environment: WSL2 on Windows 10

When program uses Command to open Bash to run a script, Bash closes immediately without running the script

I have a simple, already-working bash script set up to launch specific files with specific programs in the gaming frontend EmulationStation on Windows.
But the frontend routes its actions through a Command Prompt. And when Command is used to run the script through Bash, the Bash shell just opens and then closes immediately.
Here's an image of what shows for the instant before Bash closes.
This is only happening when going through a separate Command Prompt first, such as Windows Command Prompt or Git Command Prompt. Running the script with an appropriate argument directly through the git-bash shell works just fine.
In case you want to see the script for any reason, here it is:
#!/bin/bash
defaultemulaunch="V:/Emulation/.emulationstation/systems/retroarch/retroarch.exe -L "V:/Emulation/.emulationstation/systems/retroarch/cores/bsnes_mercury_accuracy_libretro.dll" \"$1\""
emu1names=(\
"(1999) Fire Emblem - Thracia 776.smc")
emu1launch="V:/Emulation/.emulationstation/systems/retroarch/retroarch.exe -L "V:/Emulation/.emulationstation/systems/retroarch/cores/snes9x_libretro.dll" \"$1\""
gamename=`basename "$1"`
for index in ${!emu1names[*]}
do
game=${emu1names[index]}
if [ "$game" == "$gamename" ]; then
eval "$emu1launch"
fi
done
eval "$defaultemulaunch"
But it's worth pointing out that this is happening when trying to run any bash script when starting the process from a separate Command Prompt.
Note: Git is installed on the hard drive that houses the emulation frontend (V:)---not in the user directory or programs directory of the system's OS/boot drive (C:). I mention this because git-bash's failure at an apparent "login" step except when launched directly feels like it could be a default filepath issue.
Check if that program would still open/close a Windows when executed from the CMD with:
bash -c '/v/path/to/bash/script'
In your case:
set PATH=V:\Emulation\
set GIT_HOME=V:\Emulation\Git
set PATH=%GIT_HOME%;%GIT_HOME%\bin;%GIT_HOME%\usr\bin;%GIT_HOME%\mingw64\bin;%PATH
Then:
cd V:/Emulation/.emulationstation/roms/snes/
bash -c './gamelaunch.sh "./(1990) F-Zero.sfc"'
I usually make a run.bat script which would:
set the correct PATH
launch the correct script
That way, for any of my project, I just type run.
And it runs.

How to launch GUI Emacs from command line in OSX?

How do I launch GUI Emacs from the command line in OSX?
I have downloaded and installed Emacs from http://emacsformacosx.com/.
I'll accept an answer fulfilling all of the following criteria:
The emacs window opens in front of my terminal window.
Typing "emacs" launches a GUI Emacs window. Finding files in that window will default to looking in the directory from where I started Emacs.
Typing "emacs foo.txt" when foo.txt exists launches a GUI Emacs window with foo.txt loaded.
Typing "emacs foo.txt" when foo.txt does not exist launches a GUI Emacs window with an empty text buffer named "foo.txt". Doing ^X^S in that buffer will save foo.txt in the directory from where I started Emacs.
Call the following script "emacs" and put it in your PATH somewhere:
#!/bin/sh
/Applications/Emacs.app/Contents/MacOS/Emacs "$#"
That covers #2, #3, and #4.
For #1, put this somewhere in your .emacs file:
(x-focus-frame nil)
The emacsformacosx.com site now has a How-To page, which is where the top snippet came from. There's more info there about running emacsclient and hooking Emacs up to git mergetool.
In your shell, alias the command 'emacs' to point to the OSX emacs application
In my shell (running the default bash), I have the following (in my .bashrc)
alias emacs='open -a /Applications/Emacs.app $1'
Then, typing emacs on the command line starts the emacs application.
I would, however, recommend that you open a copy of emacs and just keep it up and running. If that's the case, and you want to load a file into an existing copy of emacs, you can use the emacsclient by placing the following in your .bashrc:
alias ec='/Applications/Emacs.app/Contents/MacOS/bin/emacsclient'
Then add the following to your .emacs file to start the emacs server (which receives the emacsclient calls)
;;========================================
;; start the emacsserver that listens to emacsclient
(server-start)
Then you can type
ec .bashrc
to load a copy of .bashrc into an existing emacs session!
This improves on David Caldwell's answer by starting Emacs in the background:
#!/bin/sh
$(/Applications/Emacs.app/Contents/MacOS/Emacs "$#") &
As stated in the other answer, this covers #2, #3, and #4. For #1, put this somewhere in your .emacs file: (x-focus-frame nil).
Note that the following does not work for me -- it does not start Emacs in a directory specified on the command line (e.g. emacs .)
# NOT RECOMMENDED
#!/bin/sh
/Applications/Emacs.app/Contents/MacOS/Emacs "$#" &
I assume you either:
Start the emacs daemon on login
Have (server-start) in your .emacs
Don't mind having lots of separate copies of emacs running
If so, then I think this satisfies the original four criteria, plus one more:
The emacs window opens in front of my terminal window.
it will always open to the foreground (with x-focus-frame).
Typing "emacs" launches a GUI Emacs window. Finding files in that window will default to looking in the directory from where I started Emacs.
It will open an existing emacs window in dired mode.
Typing "emacs foo.txt" when foo.txt exists launches a GUI Emacs window with foo.txt loaded.
If emacs is already running and has a server, then it will open in the existing window and come to the foreground.
Typing "emacs foo.txt" when foo.txt does not exist launches a GUI Emacs window with an empty text buffer named "foo.txt". Doing ^X^S in that buffer will save foo.txt in the directory from where I started Emacs.
Correct.
One extra:
Control returns to the terminal session immediately after typing the command.
~/bin/emacs
#!/bin/bash
EMACSPATH=/Applications/Emacs.app/Contents/MacOS
# Check if an emacs server is available
# (by checking to see if it will evaluate a lisp statement)
if ! (${EMACSPATH}/bin/emacsclient --eval "t" 2> /dev/null > /dev/null )
then
# There is no server available so,
# Start Emacs.app detached from the terminal
# and change Emac's directory to PWD
nohup ${EMACSPATH}/Emacs --chdir "${PWD}" "${#}" 2>&1 > /dev/null &
else
# The emacs server is available so use emacsclient
if [ -z "${#}" ]
then
# There are no arguments, so
# tell emacs to open a new window
${EMACSPATH}/bin/emacsclient --eval "(list-directory \"${PWD}\")"
else
# There are arguments, so
# tell emacs to open them
${EMACSPATH}/bin/emacsclient --no-wait "${#}"
fi
# Bring emacs to the foreground
${EMACSPATH}/bin/emacsclient --eval "(x-focus-frame nil)"
fi
On Mountain Lion, I am using Yamamoto Mitsuharu's port https://github.com/railwaycat/emacs-mac-port with the following alias:
alias emacs=/Applications/Emacs.app/Contents/MacOS/Emacs
and it satisfies all of your criteria.
Just built emacs with homebrew package manager according to this guide:
http://www.emacswiki.org/emacs/EmacsForMacOS
with brew install --cocoa emacs
After that one should launch the .app version to get gui, which in my case was /usr/local/Cellar/emacs/24.3/Emacs.app/Contents/MacOS/Emacs
Further improving on David James' response the following works for me:
Per instructions to open a file from a terminal found at http://www.emacswiki.org/emacs/EmacsForMacOS#toc20
open -a /Applications/Emacs.app <file-name>
combining this with David Jame's response I've created the following emax bash script and placed it in my path at ~/bin
#!/bin/bash
(open -a /Applications/Emacs.app "$#") &
Caveat: in order to get emacs to open the current directory in Dired by name mode, you need to use
emax .
Environment:
OS X Yosemite Version 10.10.2
GNU Emacs 24.4.2 (x86_64-apple-darwin14.0.0, NS apple-appkit-1343.14)
of 2014-11-13
Simple solution...
A lot of very complex solutions to this problem are posted here. That's fair because it seems non-trivial.
However, this solution works really well for me.
ec() {
emacsclient -n $# 2> /dev/null
if [[ $? == 1 ]]; then
open -a Emacs.app -- $#
fi
}
Usage
ec file [...]
Let's unpack what's happening:
pass all the ec arguments to emacsclient and don't (-n) wait for emacs before continuing.
If Emacs is already running, we're all done and you're editing.
swallow up the error message posted by emacsclient when there's no emacs running. (2> /dev/null)
Manually handle the exit code 1 ([[ $? == 1 ]])
open Emacs.app and pass file arguments to it (paths will be correctly opened.)
You're all done, and Emacs has opened your files.
The other answers here didn't quite work for me. In particular, on my machine, the bash script
#!/bin/sh
/Applications/Emacs.app/Contents/MacOS/Emacs "$#"
always opens emacs in the home directory. To get it to open in the current working directory, I had to do
#!/bin/sh
/Applications/Emacs.app/Contents/MacOS/Emacs "$PWD/$#"
instead.
Compile Emacs according to the following steps:
./configure --with-x --prefix=/usr
make
sudo make install
And your done! It may help to download and install XQuartz, but that's just my opinion.
This is my script for open emacs/emacsclient on osx.
#!/bin/bash
# Ensure (server-start) is added in your emacs init script.
EMACS=/Applications/MacPorts/Emacs.app/Contents/MacOS/Emacs
EMACSCLIENT=/Applications/Macports/Emacs.app/\
Contents/MacOS/bin/emacsclient
# test if client already exsit.
$EMACSCLIENT -e "(frames-on-display-list)" &>/dev/null
# use emacsclient to connect existing server.
if [ $? -eq 0 ]; then
$EMACSCLIENT -n "$#"
# open emacs.app instead.
else
`$EMACS "$#"` &
fi
In all of the above when using "open" - make sure you use the "--args" option
Do not do this:
alias emacs='open -a /Applications/Emacs.app $1'
Instead this:
alias emacs='open -a /Applications/Emacs.app --args $1'
the --args option prevents "open" from consuming various options intended for Emacs.
The top answer is good, but I wanted the emacs process to run in the background so I could still use my shell. This answer appeared to do what I wanted, but didn't start emacs in the right directory, meaning absolute paths were required (or hacks to append pwd to the paths which wouldn't work in all cases). Furthermore, simply using & meant that if I killed the terminal, emacs would also be killed.
I decided to use screen and a bash function, and the following solution works for me on macOS 10.15.6 and emacs 26.2 installed with brew:
function emacs() {
screen -d -m /Applications/Emacs.app/Contents/MacOS/Emacs "$#"
}
For the meaning of the -d -m command line flags, they have a special meaning when used together and so can essentially be thought of as one command line flag. The explanation is in the manpage:
Start screen in "detached" mode. This creates a new session but doesn't attach to it. This is useful for system startup scripts.
open_emacs() {
num=$(ps aux | grep -E "[E]macs-x86_64-10_14 --|[e]macs --" | wc -l)
if [ $num -eq 0 ]; then
echo "## starting emacs"
# Run in a subshell to remove notifications and close STDOUT and STDERR:
(&>/dev/null emacsclient -t -q &)
fi
}
alias e="open_emacs"
Following line (&>/dev/null emacsclient -t -q &) will start the emacs daemon if it is not running on the background.
macOS may have defined the app name starting with E (ex: Emacs-x86_64-10_14.app), based on that you can check whether the emacs daemon running on the background or not.
Just want to update a response to this question. Since it is still a relevant question, but now there is an easier solution:
brew install --cask emacs
When this installs Emacs, it does the behavior you requested, without further intervention. It even runs the Emacs Server on startup.
Files installed/linked by default:
ebrowse -> /Applications/Emacs.app/Contents/MacOS/bin/ebrowse
emacs -> /Applications/Emacs.app/Contents/MacOS/Emacs
emacsclient -> /Applications/Emacs.app/Contents/MacOS/bin/emacsclient
etags -> /Applications/Emacs.app/Contents/MacOS/bin/etags
BTW, this is now a recommended way of installing Emacs on MacOS:
https://www.gnu.org/software/emacs/download.html#nonfree

Linux equivalent of the DOS "start" command?

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.

Resources