Is it possible to trigger a command after a specific one? - fish

Whenever I run systemctl start <something> or systemctl restart <something>, I would like to also run systemctl status <something>
Is there a way to trigger a command after a specific one has been issued?
I was considering the possibility to write an alis which would run both commands in a row but I could not understand how to keep autocompletion for the first command. Today when I type
systemctl start apa<tab>
I am autocompleted to
systemctl start apache2.service
By using a function I loose (or not?) the capacity to autocomplete and keep this autocomplete result to run a new command with it as an argument

As noted in the Fish documentation for function, the --wraps / -w flag can be used to indicate that the specified command's completions should be inherited by the new function. For example:
function sstart --wraps systemctl -d "Start service and show its status"
systemctl start $argv
systemctl status $argv
end

Related

kubectl run - How to pass some commands to be executed before reaching the interactive terminal?

When using kubectl run -ti with an interactive terminal, I would like to be able to pass a few commands in the kubectl run command to be run before the interactive terminal comes up, commands like apt install zip for example. In this way, I do not need to wait for the interactive terminal to come up and then run those common commands. Is there a way do so this?
Thanks
You can use the shell's exec to hand control over from your initial "outer" bash, responsible for doing the initialization steps you want, over to a fresh one (fresh in the sense that it does not have -c and can optionally be a login shell) which runs after your pre-steps:
kubectl run sample -it --image=ubuntu:20.04 -- \
bash -c "apt update; apt install -y zip; exec bash -il"

How do I run a Bash script before shutdown or reboot of a Raspberry Pi (running Raspbian)?

I want to run a Bash script prior to either shutdown or reboot of my Pi (running the latest Raspbian, a derivative of Debian).
e.g. if I type in sudo shutdown now or sudo reboot now into the command prompt, it should run my Bash script before continuing with shutdown/reboot.
I created a very simple script just for testing, to ensure I get the method working before I bother writing the actual script:
#!/bin/bash
touch /home/pi/ShutdownFileTest.txt
I then copied the file (called CreateFile.sh) to /etc/init.d/CreateFile
I then created symlinks in /etc/rc0.d/ and /etc/rc6.d/:
sudo ln -s /etc/init.d/CreateFile K99Dave
I'm not certain on what the proper naming should be for the symlink. Some websites say "Start the filename with a K", some say "start with an S", one said: "start with K99 so it runs at the right time"...
I actually ended up trying all of the following (not all at once, of course, but one at a time):
sudo ln -s /etc/init.d/CreateFile S00Dave
sudo ln -s /etc/init.d/CreateFile S99Dave
sudo ln -s /etc/init.d/CreateFile K00Dave
sudo ln -s /etc/init.d/CreateFile K01rpa
sudo ln -s /etc/init.d/CreateFile K99Dave
After creating each symlink, I always ran:
sudo chmod a+x /etc/init.d/CreateFile && sudo chmod a+x /etc/rc6.d/<name of symlink>
I then rebooted each time.
Each time, the file at /home/pi/ShutdownFileTest.txt was not created; the script is not executed.
I found this comment on an older post, suggesting that the above was the outdated method:
The modern way to do this is via systemd. See "man systemd-shutdown"
for details. Basically, put an executable shell script in
/lib/systemd/system-shutdown/. It gets passed an argument like "halt"
or "reboot" that allows you to distinguish the various cases if you
need to.
I copied my script into /lib/systemd/system-shutdown/, chmod +x'd it, and rebooted, but still no success.
I note the above comment says that the script is passed "halt" or "reboot" as an argument. As it should run identically in both cases, I assume it shouldn't need to actually deal with that argument. I don't know how to deal with that argument, either, so I'm not sure if I need to do something to make that work or not...
Could someone please tell me where I'm going wrong?
Thanks in advance,
Dave
As it turns out, part of the shutdown command has already executed (and unmounted the filesystem) before these scripts are executed.
Therefore, mounting the filesystem at the start of the script and unmounting it at the end is necessary.
Simply add:
mount -oremount,rw /
...at the start of the script (beneath the #!/bin/bash)
...then have the script's code...
and then finish the script with:
mount -oremount,ro /
So, the OP script should become:
#!/bin/bash
mount -oremount,rw /
touch /home/pi/ShutdownFileTest.txt
mount -oremount,ro /
...that then creates the file /home/pi/ShutdownFileTest.txt just before shutdown/reboot.
That said, it may not be best practice to use this method. Instead, it is better to create a service that runs whenever the computer is on and running normally, but runs the desired script when the service is terminated (which happens at shutdown/reboot).
This is explained in detail here, but essentially:
1: Create a file (let's call it example.service).
2: Add the following into example.service:
[Unit]
Description=This service calls shutdownScript.sh upon shutdown or reboot.
[Service]
Type=oneshot
RemainAfterExit=true
ExecStop=/home/pi/shutdownScript.sh
[Install]
WantedBy=multi-user.target
3: Move it into the correct directory for systemd by running sudo mv /home/pi/example.service /etc/systemd/system/example.service
4: Ensure the script to launch upon shutdown has appropriate permissions: chmod u+x /home/pi/shutdownScript.sh
5: Start the service: sudo systemctl start example --now
6: Make the service automatically start upon boot: sudo systemctl enable example
7: Stop the service: sudo systemctl stop example
This last command will mimic what would happen normally when the system shuts down, i.e. it will run /home/pi/shutdownScript.sh (without actually shutting down the system).
You can then reboot twice and it should work from the second reboot onwards.
EDIT: nope, no it doesn't. It worked the first time I tested it, but stopped working after that. Not sure why. If I figure out how to get it working, I'll edit this answer and remove this message (or if someone else knows, please feel free to edit the answer for me).
As I a do not have enough senority to post comments this is a new answer for which I appologize.
I added a step to ZPMMaker's answer and it seems to work for me at least.
sudo chmod u+x /etc/systemd/system/example.service

how to change systemd unit files directory?

Since I want to put all my service unit files in my own directory like /opt/myservice/, I found the way that use $SYSTEMD_UNIT_PATH in question https://unix.stackexchange.com/questions/224992/where-do-i-put-my-systemd-unit-file/367237#367237, however systemdctl can't find my service file in /opt/myservice/ after I setSYSTEMD_UNIT_PATH with shell command SYSTEMD_UNIT_PATH=/opt/myservice/, anyone knows how can it work? thx
[root#localhost system]# ls /opt/myservice/
test.service
[root#localhost system]# export SYSTEMD_UNIT_PATH=/opt/myservice/
[root#localhost system]# echo $SYSTEMD_UNIT_PATH
/opt/myservice/
[root#localhost system]# systemctl daemon-reload
[root#localhost system]# systemctl status test.service
Unit test.service could not be found.
From the document, the environment variable must be set as the kernel environement.
So, if the pid of systemd is 1, the environment must be set as kernel option, any others are invalid (e.g. /etc/profile, systemctl set-envionrment)
If you use grub-driven system, you can set it in /etc/default/grub, change the line starts with GRUB_CMDLINE_LINUX= and append SYSTEMD_UNIT_PATH=/absolute/path/to/your/services:. The last colon is required if you just want to append your services path.

ssh stops in btw while commands specified in a function

~/.config/fish/config.fish
function start
nohup VBoxHeadless -startvm $argv
end
function stop
VBoxManage controlvm $argv poweroff
end
function vm
stop vm18 & start vm18 ; sshpass -p vm18 ssh archvm
end
Test:
$ vm
VBoxManage: error: Machine 'vm18' is not currently running
appending output to nohup.out
It never does ssh for some reason. However after the machine has started if I do
$ sshpass -p vm18 ssh archvm
it works perfectly.
I don't understand why, and how to fix. I assuming appending output thing stops from running the next command.
One way to fix this is: add & in start
function start
nohup VBoxHeadless -startvm $argv &
end
Though I don't know why that works.

How to run a bash command as a different user in Capistrano?

How would I accomplish the following in Capistrano?
sudo su - postgres
/usr/pgsql-9.2/bin/pg_ctl status -D /var/lib/pgsql/9.2/data/
The following task doesn't work:
task :postgres_check do
on roles(:db) do in: :sequence |host|
execute "sudo su - postgres << EOF
/usr/pgsql-9.2/bin/pg_ctl status -D /var/lib/pgsql/9.2/data/
EOF"
end
end
The commands in the execute statement works in a bash script.
EDIT 1:
I also tried the following:
task :postgres_check do
on roles(:postgres_pref_db), in: :sequence do |host|
execute "/usr/pgsql-9.2/bin/pg_ctl status -D /var/lib/pgsql/9.2/data", :shell => "sudo su - postgres"
end
end
Which errors with:
DEBUG [68eb95f2] Command: /usr/pgsql-9.2/bin/pg_ctl status -D /var/lib/pgsql/9.2/data
DEBUG [68eb95f2] pg_ctl: could not open PID file "/var/lib/pgsql/9.2/data/postmaster.pid": Permission denied
cap aborted!
SSHKit::Command::Failed: /usr/pgsql-9.2/bin/pg_ctl status -D /var/lib/pgsql/9.2/data stdout: Nothing written
It appears that it still executing the command as the ssh user.
I came across this and explored the answer for myself. I wouldn't have accepted the answer either to I'll provide what I did.
task :copy_files do
on roles(:web) do |host|
as 'other_user' do
execute "whoami"
end
end
end
Capistrano 3 uses SSH KIT and I found these examples really helpful for getting bash commands to work inside my tasks.
https://github.com/capistrano/sshkit/blob/master/EXAMPLES.md
You'll want to checkout ssh kit and see about on(), within(), with(), as() ... they can be used nested in any order. So you end up having a lot of control even if it takes a few minutes to learn.
I think for your specific example you will want to use as() and within() to become the postgres user and run commands within a certain directory.
Also I had to disable requiretty on my /etc/sudoers for my deploy user.