I am writing a menu bar application, I need to run a method every day at a certian time. I would like it to run even if the user is not logged in. I know I need to create a helper tool registering it with launchd. Is there a good tutorial on this? I'm not new to programing but I am new to using helper tools and launched. I have been doing some reading and came across SMJob, and I know I can use it to create helper tools just not how to use it. I just need some direction with this.
Take a look at Daemons and Services Programming Guide
The solution is to create some command line utility, make launchd plist file in the /Library/LaunchDaemons directory (note that it must be owned by root:wheel and have 0644 mode) and load job via command sudo launchctl load -w /Library/LaunchDaemons/your.plist (flag -w forces your job to launch at every boot). For the running your job periodically set StartInterval or StartCalendarInterval key in your plist (see "Creating Launch Daemons and Agents" -> "Creating a launchd Property List File" -> "Running a Job Periodically" in the guide for the example")
Related
I have designed a GUI that I want to run as soon as I turn on my Raspberry Pi. It is currently set up to automatically log in as user on startup, but if that makes the process more difficult I can change that. My Raspi runs on Raspbian 10 (buster), which has made things difficult since I can only find tutorials for Raspbian 8 or so.
I have tried modifying autostart folder, but it is not in the same location as it was in previous Raspbian versions and doesn't seem to be working the way it used to. Tutorials have said to create a .desktop file in /home/pi/.config/autostart but I don't have a .config folder, or at least it's hidden. For me, autostart is in /etc/xdg/autostart and when I try to create a new file here using nano in the terminal, I get the message [Directory '/etc/xdg/autostart' is not writable] and it doesn't save my file.
I have also tried calling my script in /etc/rc.local but it did nothing. Some have said it doesn't work for GUIs.
Here's what I type into terminal:
$ nano /etc/xdg/autostart/gui.desktop
and a new file pops up, but at the bottom I get the warning [Directory '/etc/xdg/autostart' is not writable]
How can I get my GUI script to run on startup with Raspbian 10 (buster)?
There are a number of issues here, first when you are looking at tutorials recognize that Linux distros are built in layers, for simplicity let's say your "layer stack" looks like this: kernel, systemd, x11, xdg, lxde. The kernel boots, then starts systemd, which then starts x11 (and a lot of other stuff), x11 starts xdg (and some other stuff, I think), lxde is started by either x11 or xdg I'm not sure which.
You want to add something to this process, you can do it at the kernel level (bad idea), at they systemd level (probably not right unless its a daemon), at the x11 level (still probably bad as you still don't have a user session yet), or at the xdg or lxde level.
xdg is probably the right place as it has all you need ( a gui, a user session) while being common (xdg will still work if you switch window managers, probably)
With that out of the way, why isn't your solution of modifying xdg working? It's because '/etc/xdg/autostart' is a system configuration directory. Any changes made to it will apply to all users. You may want this, but the system is trying to protect other users on your system and only allows root to make changes to everyone. If you want to do that use "sudo" (documented elsewhere on stack exchange and the internet). If you want to do it just for you use ~/.config/autostart, (https://wiki.archlinux.org/index.php/XDG_Autostart) you might need to create that directory with "mkdir ~/.config/" and then "emacs ~/.config/autostart"
Would it be better to have the python program run in a terminal window from startup? That way you would see what it is doing in case of errors.
If so, perhaps check this out https://stackoverflow.com/a/61730679/7575617
By the way, in the file manager, hit CTRL+H to toggle viewing hidden files and folders.
I like using WinSCP for keeping a remote directory up to date, but it locks up the rest of the interface while in use. Is there any way I can configure WinSCP to run on startup (in the background) and keep a certain remote directory up to date with a local copy without impacting the rest of WinSCP's interface?
You can run two instances of WinSCP. One for keeping remote directory up to date, the other for an interactive use.
You can have WinSCP automatically start keeping remote directory up to date. There are two ways, GUI mode and scripting.
GUI mode:
C:\path_to_winscp\WinSCP.exe session_name /defaults
/keepuptodate // C:\local_path /remote_path
(Line break added for readability. The /defaults make WinSCP skip the options dialog.)
For details, see https://winscp.net/eng/docs/commandline
This way you cannot make WinSCP open in the background. You have to manually press the Minimize button.
Scripting mode:
C:\path_to_winscp\WinSCP.exe /console /command "option batch abort"
"open session_name" "keepuptodate C:\local_path /remote_path"
(Line break added for readability.)
For details, see https://winscp.net/eng/docs/guide_automation
If you store this command to a shortcut, you can set it's Run property to Minimized.
For both modes, you can store the command to a shortcut and move it to C:\Users\username\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup to have it automatically started with Windows.
Minimizing to a tray:
Minimizing to a tray is a global preference option:
https://winscp.net/eng/docs/ui_pref_window
If you do not want to enable it globally (it would apply even to the WinSCP instance for an interactive use), add this to the command-line:
/rawconfig Interface\MinimizeToTray=1
See Raw configuration.
On windows and such I used to use a trick to find out of a file is currently in use (written specifically).
I use to open the file for writing and if it failed most likey another process is busy accessing it.
Sadly these trick (using C OPEN with exclusive lock for writing) doesn't work on my Mac. While my curl in a terminal is still writing my -fileBusy() check fails.
fcnt call on the fd with F_GETLK doesn't reveal any locking as well.
Is there any chance for me to detect if a file is in use by another process?
Ps> listening for fsevents can't be done because my app launches after the is created by the other app / process.
Apple confirmed via email that the solution described in the link below is a valid one and not considered a private API.
More information:
http://lists.apple.com/archives/cocoa-dev/2010/May/msg01455.html
You could try running the following shell command using NSTask:
lsof -Fc path/to/thefile
That will give you the process ID and name of any process(es) that have thefile open.
I'm working on an app that needs to use dd (I do this with a shell script in the app bundle, that collects parameters from the app itself, makes some checks and then launches dd).
To make this operation I need to call dd with root, and I already looked at several solutions on StackOverflow. The simplest to implements seemed to me this one http://www.sveinbjorn.org/STPrivilegedTask
Problem is that my NSTask makes some complex read/write operations (not present in STPrivilegedTask) and does not need to be all privileged.
So I wrote a small helper tool in c that calls my script with correct parameters from my app. The solution I thought is to use the STPrivilegedTask to SUID once the fly my small helper tool, so I can launch it (and so my script and dd) with root, and soon after successful launch I set back the helper tool to non SUID (and I do the same if any error, on app exit, app start etc.. to be safer).
I implemented it and works quite well, maybe it's not perfect but I think that being all inside the bundle, and working with the helper tool in SUID just for the launch sounds safe enough.
Any thoughts?
Thanks!
You can use a sandbox for running the new Process in your NSTask
sandbox-exec -f <profile> <command>
sandbox-exec -f my_profile.sb "/bin/dd -if=/dev/disks01 of=/dev/target"
http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man1/sandbox-exec.1.html
You have some profile examples in here
/usr/share/sandbox/
You have to give enough access for dd to work, I haven't tried or checked what dd requires, I would start with something like this:
(version 1)
(deny default)
(debug deny)
(import "system.sb")
(allow file-read-data file-write-data file-ioctl (regex #"^/dev/.*$"))
(allow process-exec (literal "/usr/sbin/helper"))
Update:
Worth mention, you can use
sandbox-exec -p command
Is there a way to get the current working directory of a process using it's PID programmatically on OS X?
Cocoa, Carbon, or AppleScript are all acceptable.
It is not acceptable to send "pwd" to the current terminal window/tab (Do not want to affect the workspace).
The linux command "pwdx" also is also unacceptable (just in case you read over the "Cocoa" part)
On 10.5 and later:
lsof -a -p $PID -d cwd -Fn
(Prefix with sudo if the process is owned by root.)
The following AppleScript is a partial solution for your problem. Given the UNIX pid in the variable thePID it first gets the name of the process. It then sends the do shell script command to the application process which will result in a child shell process being spawned. The child process inherits the current directory which can then be determined by running the pwd command.
tell application "System Events"
set theName to name of first process whose unix id is thePID
end tell
tell application theName
do shell script "/bin/pwd"
end tell
The script does not work for processes that do not link to the AppleEvent framework (e.g., pure POSIX processes).