How to automatically start programs in a specific order? - i3

I have these lines in my i3 configuration file:
# Startup applications.
exec firefox
exec gnome-terminal
exec nautilus
These lines start firefox, gnome-terminal and nautilus as expected, but the order in which they start is unpredictable. Is there a way to start these applications in a way that makes the windows appear in the order that I want? (i.e. firefox, then gnome-terminal, then nautilus).

Refer to Layout saving in i3.
Add this to the i3 configuration file:
# Create specific layout for applications.
exec --no-startup-id "i3-msg 'workspace 1; append_layout ~/.config/i3/workspace-1.json'"
# Start applications.
exec firefox
exec gnome-terminal
Create ~/.config/i3/workspace-1.json:
// Layout of a workspace.
{
"layout": "tabbed",
// To get a window's class name, run xprop and click on the window.
// You will see the following output:
// WM_CLASS(STRING) = "InstanceName", "ClassName"
// Alternatively, "swallow" by the window's title.
"nodes": [
{"swallows": [{"class": "^Firefox$"}]},
{"swallows": [{"class": "^Gnome-terminal$"}]}
]
}

You can save layouts so that each application is captured by a predefined window container. Making it truly automatic requires a little extra scripting. Examples from my configuration:
i3 config
assign [class="^Vivaldi-stable$"] 1
assign [class="^Keepassx2$"] 2
assign [class="^Thunderbird$"] 2
....
# last line
exec ~/.config/i3/restore.sh &
restore.sh
#!/bin/sh
for layout in ~/.config/i3/layouts/*; do
i3-msg "workspace $(basename "$layout" .json); append_layout $layout"
done
(vivaldi-stable &)
(keepassxc &)
(thunderbird &)
If you want to see the full version, my dotfiles are on GitHub.

Related

How to Pass commands to custom linux Service using bash / terminal

Goal: Run a custom bash script as a service in linux and allow me to pass commands to it like you can to most other services via terminal/bash.
I already have a script set up and tested that can do what I need it to, except I can't figure out how to be able to pass commands to it like you would other services.
Example: nano opens up the nano editor to read specified file.
I want to perform 'fan on', which will call the new service 'fan' and execute the 'on' command.
Bonus: Being able to save the variables into a config file to be modified later on. But for now, I have the variables set at top of script so its not totally necessary.
Current Unit File:
[Unit]
Description=Fan control Service
[Service]
Type=simple
Restart=always
RestartSec=30
ExecStart=/home/pi/Documents/FanControl.sh
User=pi
[Install]
WantedBy=multi-user.target
Script:
#!/bin/bash
#########################################################
# User Settings
#GPIO Pin Number to use to control fan transistor.
fanpin=3
#Celsius temp to turn fan on/off
offtemp=55
ontemp=60
#Turn on the looping script automatically or not
autostart=TRUE
#Determine how often to scan temp and turn fan on/off if in auto
sleepinterval=10
#########################################################
#Misc Variables used in script - Leave these alone - Base Settings
MaxTemp=0
FanState=OFF
mode=MANUAL
auto=FALSE
#########################################################
# Functions Described Below
#########################################################
before-start() {
# Check if gpio is already exported
if [ ! -d /sys/class/gpio/gpio$fanpin ]
then
#Export the Pin
echo $fanpin > /sys/class/gpio/export
sleep 1 ;# Short delay while GPIO permissions are set up
echo Fan Pin Exported Successfully.
# Setup the pin as an output
sudo echo "out" > /sys/class/gpio/gpio$fanpin/direction
fi
}
#Function to turn fan on
on() {
# Sets FanPin to high
echo "1" > /sys/class/gpio/gpio$fanpin/value
FanState=ON
mode=Manual
auto=FALSE
echo Fan Turned on -- Mode set to Manual.
echo
}
#Function to turn fan off
off() {
# Sets FanPin to low
echo "0" > /sys/class/gpio/gpio$fanpin/value
FanState=OFF
mode=Manual
auto=FALSE
echo Fan Turned off -- Mode set to Manual.
echo
}
#Function to set the variables to values
#Haven't actually tested this function yet
Set() {
if $2 = "ontemp"
then
ontemp=$2
else
$2=$3
fi
}
#########################################################
# Begin Service Execution Code
#########################################################
#Don't know whow to write this section to keep it running as a service
#But it works well for testing purposes
before-start
on
sleep 3
off
echo
read -p "Select an action": Q
$Q
echo
action="$1"
serviceName="Fan-Control Service"
echo Exiting Fan Service
I can use systemctl daemon-reload and it can load the service.
I can use 'systemctl start fan' and the service starts successfully without error. it will also run the fan for a few seconds, so i know its starting fine.
When attempting to use 'fan on' as a bash command, i get "command not found"
- how can i get this as a working command?
- what changes do I need in the script to keep it alive to be able to pass such commands to it later on?
It is atypical for services to respond to interactive commands other than service-management commands drawn from a pre-defined set. If that's the concept you are trying to prove then I would suggest choosing a different direction.
But if you must do it, then you have viable alternatives:
for an on / off toggle, consider setting up a signal handler in the service script, say for SIGUSR1. You can send signals directly via the kill command, but I would recommend instead providing a separate script for the purpose.
for more complex instructions or more than a very small number of distinct instructions, you need some kind of communication channel. The script could potentially use a FIFO or a socket for this purpose, and in that case I would again recommend a separate script for sending commands. But this will require your service to be substantially more complex.
In any case, do note that although there's a long tradition of service-control scripts, service implementations themselves are rarely scripts. They are normally compiled programs, typically written in C, as this provides more direct access to the system and finer control, and is also considered by many to be more secure (when done competently).

gnome-terminal: How to close the original tab?

Just wrote a script that would open 3 new tabs in a window.
tab_init.sh:
#!/bin/bash
# options="--hide-menubar --geometry=140x42"
options=""
options_each=()
# tabs
cmds[1]="cd ~/a; clear"
cmds[2]="cd ~/b; clear"
cmds[3]="cd ~/c; clear"
for i in 1 2 3; do
options_each+=(--tab -e "bash -c '${cmds[i]} ; bash'" )
done
gnome-terminal $options "${options_each[#]}" &
exit 0
Current result:
After executing the script, there will be 3 more tabs opened in current window, plus the original tab, there would be 4 tabs.
Desired result:
But what I want is to open the new tabs in a standalone window, without including any other tab.
The questions are:
How to close the original tab automatically from the script, so that there would be only 3 tabs(the new ones) after executing the script?
Or, can I open the 3 new tabs in a new window, not in the original window, so that it doesn't matter whether I close the original tab.
Kind of found a way to do this.
First, make soft link of the script into $PATH.
e.g link it as tab_init somewhere,
Then, define command shortcuts in ~/.bashrc, to add the extra behavior.
e.g
alias tabinit='tab_init; exit' # init tabs, and close original tab,
alias tabinitne='tab_init' # init tabs, and keep the original tab,
Now, could use command tabinit or tabinitne to choose the behavior desired.

How to check is maximized any window in XFCE?

I want to change top panel color and alpha when any window is maximized.
For now I have something like this:
#!/bin/bash
while [ 1 = 1 ]
do
if window_is_maximized
then
xfconf-query -c xfce4-panel -p /panels/panel-0/background-alpha -s 100
else
xfconf-query -c xfce4-panel -p /panels/panel-0/background-alpha -s 50
fi
done
Maximized windows in X do not have a special state that you can test reliably. From a script, you can use xwininfo:
You can check if the window happens to be the same size as the root (main) window, and its position is the upper-left corner.
If you happen to be using a window manager which supports certain EMWH properties (_NET_WM_STATE_FULLSCREEN, _NET_WM_STATE_MAXIMIZED_VERT, _NET_WM_STATE_MAXIMIZED_HORZ), your script could check for those. But in a quick check for window managers which might do that, I found none.

Create window into screen

Is there a way to list all window names and depending on the result, creating a new window with a specific name into this (running) session.
How to create a new screen session with assigned window names is documented in the man pages, but i could find information about a solution to the problem above.
From outside the screen session, I don't think so.
But if you are starting from inside, in one of the windows of the right screen session, then yes:
for window_name in foo bar baz quux ; do ## ...
screen -t $window_name
done
You can even get fancy and run some initial commands in each window! This snipped of copy-paste bash helps me get back to work quickly after a reboot. Once I've started the screen session:
for n in $(seq 1 8) ; do ## ...
screen -t proj_$n bash -c "cd /src/foo/proj_$n*/ ;"\
' eval `set_proj_env_vars.sh` ; svn status ; make clean ; make ;'\
' exec bash --login'
done
...and as a great side effect the screen windows are numbered for the various checkouts, where each one can be working on a different bug/feature. Overkill? Totally! But it's a fun hack.

current directory doesn't appear in title bar when running under screen

My xterm $prompt variable in my .tcshrc is:
set prompt="%{\033]0;%m:%~\007%}%{^[[;37;1m%}%B%{^[[;34;1m%}%m%{^[[;34;1m%}:%b%c%# "
The highlighted part above (%{\033]0;%m:%~\007%}) puts the hostname (%m) and the current directory (%~) in the title bar. (At least I think that that's what puts it in the title bar; it's been a while since I fiddled with this prompt).
When I run screen, however, the current directory stops getting updated when I change directories.
My questions:
How can I make this prompt work in screen?
Is there a better way to display the current directory in the title bar?
I am running linux with xterm and tcsh.
I think there is no direct way, because of the way screen works. However screen can display its own status bar, that you can define in .screenrc. Here's mine for instance :
hardstatus alwayslastline
hardstatus string '%{= kG}[ %{G}%H %{g}][%=%{=kw}%?%-Lw%?%{r}(%{W}%n*%f%t%?(%u)%?%{r})%{w}%?%+Lw%?%?%= %{g}][%{B}%Y-%m-%d %{W}%c %{g}]'
Firstly, to make it work you must check where exactly is the line with set prompt=blah-blah in your .tcshrc. For example, the code below that perfectly works in plain xterm would not work under screen in xterm:
switch ($TERM)
case "xterm*":
set prompt="%{\033]0;${HOME:t}#%m:%l:%c08\007%}%{\033[36m%}%l:%c02%#%{\033[0m%} "
# update xterm title to display current cmd in it
alias postcmd 'echo -n "\033]0;${HOME:t}#`hostname`:${tty} \!#:q\007"'
...
because screen by default sets $TERM variable to screen and not xterm! So you must add:
case "screen":
# lame, but prevents an error in screen after 'su - root'
if (! $?WINDOW) setenv WINDOW 1
set prompt="%{\033]0;${HOME:t}#%m:${WINDOW}:%c08\007%}%{\033[36m%}%c02%#%{\033[0m%} "
alias postcmd 'echo -n "\033]0;${HOME:t}#`hostname`:${WINDOW} \!#:q\007"'
...
Secondly, make sure yo have this line in ~/.screenrc:
termcapinfo xterm* 'hs:ts=\E]2;:fs=\007:ds=\E]2;\007'

Resources