I'm looking for an Applescript to toggle Web Sharing in Snow Leopard. I tried this but it doesn't disable, just restarts it when I run it again. Or a shell command as long as I can turn it into a Quicksilver action. That's my end goal. Thanks so much!
You can use the following shell script to toggle the enabled state of a Mac OS X service:
#!/bin/sh
# toggle OS X service
if [ "$#" -ne "1" ]
then
echo 1>&2 Usage: `basename $0` service
echo 1>&2 Toggle the enabled state of the given service.
exit 2
fi
SERVICE_NAME=$1
SERVICE_PLIST=/System/Library/LaunchDaemons/$SERVICE_NAME.plist
if [ ! -f "$SERVICE_PLIST" ]
then
echo 1>&2 Service $SERVICE_NAME is not available.
exit 1
fi
/sbin/service --test-if-configured-on "$SERVICE_NAME"
if [ $? -eq 0 ]
then
/bin/launchctl unload -w "$SERVICE_PLIST"
else
/bin/launchctl load -w "$SERVICE_PLIST"
fi
The script uses the service command to determine if the service is on and then toggles its state by invoking launchctl.
The name of the service has to passed as the only argument. To toggle web sharing run:
sudo toggle_service.sh org.apache.httpd
To invoke the shell script via AppleScript you can use the do shell script command:
do shell script "toggle_service.sh org.apache.httpd" password "pwd" with administrator privileges
Use the password parameter to avoid being prompted.
Related
I have a simple shell script where I need to check if my EMR job is running or not and I am just printing a log but it does not seem to work properly when scheduling the script using cron as it always prints the if block statement because the value of "status_live" var is always empty so if anyone can suggest what is wrong here otherwise on manually running the script it works properly.
#!/bin/sh
status_live=$(yarn application -list | grep -i "Streaming App")
if [ -z $status_live ]
then
echo "Running spark streaming job again at: "$(date) &
else
echo "Spark Streaming job is running, at: "$(date)
fi
Your script cannot run in cron because cron script has no environment context at all.
For example try to run your script as another use nobody that has no shell.
sudo -u nobody <script-full-path>
It will fail because it has no environment context.
The solution is to add your user environment context to your script. Just add source to your .bash_profile
sed -i "2a source $HOME/.bash_profile" <script-full-path>
Your script should look like:
#!/bin/sh
source /home/<your user name>/.bash_profile
status_live=$(yarn application -list | grep -i "Streaming App")
if [ -z $status_live ]
then
echo "Running spark streaming job again at: "$(date) &
else
echo "Spark Streaming job is running, at: "$(date)
fi
Now try to run it again with user nobody, if it works than cron will work as well.
sudo -u nobody <script-full-path>
Note that cron has no standard output. and you will need to redirect standard output from your script to a log file.
<script-full-path> >> <logfile-full-path>
# $? will have the last command status in bash shell scripting
# your complete command here below and status_live is 0 if it finds in grep (i.e. true in shell if condition.)
yarn application -list | grep -i "Streaming App"
status_live=$?
echo status_live: ${status_live}
if [ "$status_live" -eq 0 ]; then
echo "success
else
echo "fail"
fi
I wrote a little helper to start an Android emulator which looks like this:
# START ANDROID EMULATION
android-sim () {
if [[ -z "$1" ]]; then
echo "No Android device supplied as argument!"
return 1
fi
if [[ -d "$ANDROID_HOME" ]]; then
cd "$ANDROID_HOME/emulator" &>/dev/null
./emulator "#$1" &>/dev/null &
cd - &>/dev/null
else
echo "The variable ANDROID_HOME is not set to a correct directory!"
fi
}
I tried to suppress all the generated output with &>/dev/null. For the emulator itself I also tried to put the execution in the background.
But when I run the function I still get the following output:
# before exeuction
[09:11:48] sandrowinkler:~ $ android-sim pixel-29
[1] 23217
# after execution, I closed the emulator via GUI
[09:11:55] sandrowinkler:~ $
[1]+ Done ./emulator "#$1" &> /dev/null
(wd: /usr/local/share/android-sdk/emulator)
(wd now: ~)
According to this superuser post and this unix post I used the right way to silence the output. So what am I doing wrong here?
PS: I would also appreciate tips to improve my Bash code.
If the monitoring of the background job is not needed the double fork may be a solution.
( ./emulator "#$1" &>/dev/null & )
when the parent exit before the child process the child process is attached to process 1 so no more monitored by current shell.
also looking at the script, cd - could be avoided changing directory in the sub shell:
(
cd "$ANDROID_HOME/emulator"
./emulator "#$1" &
) &>/dev/null
because current shell will not be affected by subshell change directory
You've done it correctly. That output is not from your script, but from the shell, displaying information about the background process (the PID, the done message and the working directory when in ends).
If you redirect the input externally, like this:
andoroid-sim foo > log.txt
and after execution you open log.txt, you'll see what actually your program outputed (and those messages won't be there, even if they appear in the console).
This question already has answers here:
How can a program detect if it is running as a systemd daemon?
(3 answers)
Closed 2 years ago.
As a Unix sysadmin, we experience issues with others (E.g. DBAs) starting/stopping services by interactively running scripts. This means systemd has no knowledge of the state of a service. To prevent this, I insert a conditional in the scripts like this:
# The systemd unit creates a ORACLE_SYSTEMD_UNIT environment variable. If this
# isn't set (i.e. Not running through systemd) then abort.
if [ "${ORACLE_SYSTEMD_UNIT:+set}" == "" ]; then
logmsg "Not initiated through systemd. Aborting"
exit 2
fi
Can anyone suggest a cleaner method, or perhaps an Environment variable that is automatically set by the systemd unit activation?
As pointed out in the comments, you can check the command name of the parent process. In bash the process id of the parent process is stored in $PPID. The command name for a given pid can be obtained by ps. This only works if your script is running directly under systemd.
if [ "$(ps -o comm= $PPID)" != systemd ]; then
echo "Not running under systemd"
fi
If you also want to check the parents of the parents and so on, iterate/recurse. The parent of any pid can be obtained by ps too.
runsUnderSystemd() {
pid="${1-$$}"
[ "$pid" = 0 ] && return 1
[ "$(ps -o comm= "$pid")" = systemd ] ||
runsUnderSystemd "$(ps -o ppid= "$pid" | tr -d ' ')"
}
if ! runsUnderSystemd; then
echo "Not running under systemd"
fi
With pstree this can be shortend to
if ! pstree -s $PPID | grep -Fwq systemd; then
echo "Not running under systemd"
fi
Alternatively, you can set an environment variable in your .service file for systemd ...
[Service]
Environment="STARTED_BY_SYSTEMD=yes"
... which can then be checked in all children of the started service
if [ "$STARTED_BY_SYSTEMD" != yes ]; then
echo "Not running under systemd"
fi
Please note that both approaches are just safeguards against mistakes. An attacker could fake or hide systemd in either way.
I have WSL bash running in a cmd. I don't use it for anything, it just hangs there to keep the WSL system alive.
When I start X applications:
bash -c "DISPLAY=:0 xmessage hello &"
I get this result:
I can close down the command window without any problems, but it's rather annoying.
How can run commands without getting this cmd window every time?
Here's a simpler solution, which, however, requires a WSH-based helper script, runHidden.vbs (see bottom section):
wscript .\runHidden.vbs bash -c "DISPLAY=:0 xmessage 'hello, world'"
To apply #davv's own launch-in-background technique to avoid creating a new bash instance every time:
One-time action (e.g., at boot time): launch a hidden, stay-open bash window. This spawns 2 bash processes: the Windows bash.exe process that owns the console window, and the WSL bash process (owned by the WSL init singleton), which is then available for servicing background commands.
wscript .\runHidden.vbs bash # hidden helper instance for servicing background commands
For every X Window-launching command: Terminate each command with & to have it be run by the hidden WSL bash instance asynchronously, without keeping the invoking bash instance alive:
wscript .\runHidden.vbs bash -c "DISPLAY=:0 xmessage 'hello, world' &"
runHidden.vbs source code:
' Simple command-line help.
select case WScript.Arguments(0)
case "-?", "/?", "-h", "--help"
WScript.echo "Usage: runHidden executable [...]" & vbNewLine & vbNewLine & "Runs the specified command hidden (without a visible window)."
WScript.Quit(0)
end select
' Separate the arguments into the executable name
' and a single string containing all arguments.
exe = WScript.Arguments(0)
sep = ""
for i = 1 to WScript.Arguments.Count -1
' Enclose arguments in "..." to preserve their original partitioning, if necessary.
if Instr(WScript.Arguments(i), " ") > 0 then
args = args & sep & """" & WScript.Arguments(i) & """"
else
args = args & sep & WScript.Arguments(i)
end if
sep = " "
next
' Execute the command with its window *hidden* (0)
WScript.CreateObject("Shell.Application").ShellExecute exe, args, "", "open", 0
Even when launched from a GUI app (such as via the Run dialog invoked with Win+R), this will not show a console window.
If your system is configured to execute .vbs scripts with wscript.exe by default (wscript //h:wscript /s, which, I think, is the default configuration), you can invoke runHidden.vbs directly, and if you put it in your %PATH%, by filename (root) only: runHidden ....
Note that use of the script is not limited to console applications: even GUI applications can be run hidden with it.
There's another simple solution, it requires an external executable though. It has no dependencies and was recommended by aseering on GitHub.
you can launch bash via run.exe: run.exe bash.exe -c "<whatever Linux command>". (run.exe is available here: http://www.straightrunning.com/projectrun/ , make sure you download the 64-bit version, the 32-bit version will not be able to find or run bash).
With run on the search PATH, you can just call
run bash -c "DISPLAY=:0 xmessage hello"
So I just made this workaround for now. I really hope that there's a better way than this, but here it goes:
In the command prompt that lives purely to keep WSL alive, I have this script running:
wsl_run_server
#!/bin/bash
set -e
nc -kl 127.0.0.1 15150 | sh
And then I have this command to execute commands in background:
wsl_run_command
if ! pidof -x bin/wsl_run_server; then
echo wsl_run_server isnt running!
exit 1
fi
echo \($#\) \& | nc localhost 15150
from windows I then call:
bash -c "DISPLAY=:0 ~/bin/wsl_run_command xmessage hello"
There no longer is a need to have that command window pop up anymore with WSLg recently added to the mix. You just can call bash using WSLg, like so (I use Ubuntu currently in WSL):
wslg ~ -d Ubuntu bash
This will create a BASH session that will just sit there without being seen. Alternatively, you can do what I do and run a few services that stay running. I created a script that checks for running services, and if it doesn't find them running, will run them. Create the file in /usr/bin:
sudo touch /usr/bin/start-wsl-services
sudo nano /usr/bin/start-wsl-services
Past the following into the file:
#!/bin/bash
# Check for and run System-wide DBus service.
SERVICE="dbus-daemon"
if pgrep -x "$SERVICE" >/dev/null
then
pgrep -a "$SERVICE"
else
sudo /etc/init.d/dbus start
pgrep -a "$SERVICE"
fi
# Check for and run CUPS Printing Service.
SERVICE="cupsd"
if pgrep -x "$SERVICE" >/dev/null
then
pgrep -a "$SERVICE"
else
sudo /etc/init.d/cups start
pgrep -a "$SERVICE"
fi
# Check for and start Freshclam CLAMAV Update service.
SERVICE="freshclam"
if pgrep -x "$SERVICE" >/dev/null
then
pgrep -a "$SERVICE"
else
sudo /etc/init.d/clamav-freshclam start
pgrep -a "$SERVICE"
fi
# Check for and start SANED Scanner service.
SERVICE="saned"
if pgrep -x "$SERVICE" >/dev/null
then
pgrep -a "$SERVICE"
else
sudo /etc/init.d/saned start
pgrep -a "$SERVICE"
fi
# Check for and start screen-cleanup service.
SERVICE="screen-cleanup"
if pgrep -x "$SERVICE" >/dev/null
then
pgrep -a "$SERVICE"
else
sudo /etc/init.d/screen-cleanup start
pgrep -a "$SERVICE"
fi
# Check for and start Preload service.
SERVICE="preload"
if pgrep -x "$SERVICE" >/dev/null
then
pgrep -a "$SERVICE"
else
sudo /etc/init.d/preload start
pgrep -a "$SERVICE"
fi
# Prestart LibreOffice twice for faster loading.
#/usr/bin/libreoffice --terminate_after_init
#sleep 5
#/usr/bin/libreoffice --terminate_after_init
# Check for error, make sure all functions called and run, and pass the result on to calling process.
if [[ $? -ne 0 ]] ; then
exit 1
else
exit 0
fi
Save and exit the file, and then make it executable:
sudo chmod +x /usr/bin/start-wsl-services
I then call this using a shortcut that runs a startup script at startup. Or you can just run it manually. The command I use in the startup script is:
C:\Windows\System32\wslg.exe -d Ubuntu -- /usr/bin/start-wsl-services
The startup command script I use (named StartWSL.cmd) is as follows:
#echo off
echo Starting WSL Linux...
:RETRY
C:\Windows\System32\wslg.exe -d Ubuntu -- /usr/bin/start-wsl-services
REM - C:\Windows\System32\bash.exe -c '/usr/bin/start-wsl-services'
IF %ERRORLEVEL% NEQ 0 (GOTO RETRY)
REM - Allow time to see all results.
timeout /t 5 /nobreak >NUL
REM - Uncomment below line for troubleshooting.
REM - pause
exit 0
And that's how I now keep WSL running in the background on Windows 11, and similar to how I did it on Windows 10.
run command background
screen -dmS [name] [command]
example
screen -dmS gui bash -c "DISPLAY=:0 xmessage hello"
create a shortcut on windows desktop(run in wsl)
wslusc screen -dmS gui bash -c "DISPLAY=:0 xmessage hello"
So I wrote the Arch Linux rc.d script for mongod daemon (following an example), but when I do:
sudo rc.d start mongod
it just gets stuck on:
:: Starting /usr/bin/mongod [BUSY]
and never transitions to "DONE" phase. Any tips?
Here is my script:
#!/bin/bash
# import predefined functions
. /etc/rc.conf
. /etc/rc.d/functions
# Point to the binary
DAEMON=/usr/bin/mongod
# Get the ARGS from the conf
. /etc/conf.d/crond
# Function to get the process id
PID=$(get_pid $DAEMON)
case "$1" in
start)
stat_busy "Starting $DAEMON"
# Check the PID exists - and if it does (returns 0) - do no run
[ -z "$PID" ] && $DAEMON $ARGS &> /dev/null
if [ $? = 0 ]; then
add_daemon $DAEMON
stat_done
else
stat_fail
exit 1
fi
;;
stop)
stat_busy "Stopping $DAEMON"
kill -HUP $PID &>/dev/null
rm_daemon $DAEMON
stat_done
;;
restart)
$0 stop
sleep 1
$0 start
;;
*)
echo "usage: $0 {start|stop|restart}"
esac
I've looked at how apache does it, but I can't figure out what they are doing that's different. Here's a piece of their httpd script:
case "$1" in
start)
stat_busy "Starting Apache Web Server"
[ ! -d /var/run/httpd ] && install -d /var/run/httpd
if $APACHECTL start >/dev/null ; then
add_daemon $daemon_name
stat_done
else
stat_fail
exit 1
fi
;;
For one thing, you are passing an $ARGS variable that is never actually defined. You will probably want to either pass some configuration options, or the location of a mongodb.conf file using the -f or --config option, to inform the daemon of the location of your database, log file, IP bindings, etc.
The mongod defaults assume that you database location is /data/db/. If this does not exist, or the daemon does not have permissions to that location, then the init script will fail.
You should probably also run the daemon with a user account other than yourself or root (the default pacman package creates a user named mongodb), and give this user read/write access to the data path and log file.
[ -z "$PID" ] && /bin/su mongodb -c "/usr/bin/mongod --config /etc/mongodb.conf --fork" > /dev/null
I would suggest referring to the mongodb init script provided in the Arch Community package, and comparing that to what you have here. Or, install MongoDB using pacman, which sets all of this up for you.
If all else fails, add some 'echo' commands inside of your if and else blocks to track down exactly where the init script is hanging, check mongodb's logs, and report back to us.