I'm using brew which installs python (2.7.2) in /usr/local/bin/
However, the default system python (2.7.1) is executed instead at /usr/bin/, which seems to be because it doesn't obey any of the bash PATH environment variables.
Also, it can't find my modules, as they are installed at /usr/local/lib/python:/usr/local/Cellar/python/2.7.2/lib/python2.7/site-packages.
I've been trying the following with Python.sublime-settings, but it doesn't work:
{
"path": "/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin",
"env": ["PYTHONPATH", "/usr/local/lib/python:/usr/local/Cellar/python/2.7.2/lib/python2.7/site-packages"],
"cmd": ["python", "-u", "$file"],
"file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
"selector": "source.python"
}
How can I make Sublime Text obey these environment variables?
env needs to be a JSON object, or dictionary if you will, like this:
"env":
{
"PYTHONPATH":"/usr/local/lib/python:/usr/local/Cellar/python/2.7.2/lib/python2.7/site-packages"
},
I got it by setting my paths system wide by doing the following:
## PATH
export PATH=/usr/local/bin:/usr/local/share/python:$PATH
## PYTHON
export PYTHONPATH=/usr/local/lib/python:$PYTHONPATH
# make systemwide
launchctl setenv PATH $PATH
launchctl setenv PYTHONPATH $PYTHONPATH
Edit:
Damn, this doesn't work for python, just for PYTHONPATH, when I try it, it still gives the wrong python. Code used to check python binary location:
import sys, os
print os.path.dirname(sys.executable)
Edit2:
Fixed this by hardlinking to the right python binary in Python.sublime-build:
{
"cmd": ["/usr/local/bin/python", "-u", "$file"],
"file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
"selector": "source.python"
}
Edit 3:
Debugging PYTHONPATH variable issues can be made easier by also printing os.environ at the top of your script. Sublime Text 2 variable names apparently do NOT work for 'env'.
Sorry to bump an old post but if people land on this page looking for a way to make sublime2 use a custom $PATH so plugins (e.g a shell plugin) use your current systems $PATH this worked for me:
Create a file (plugin):
~/Library/Application Support/Sublime Text 2/Packages/User/Any_ol_name.py
Then paste this code in:
import os
# Tweak line below as needed for your $PATH
LOCAL = '/usr/local/bin:/usr/local/sbin'
# Sublime's default path is
# /usr/bin:/bin:/usr/sbin:/sbin
# it'll be prepended to your custom one
os.environ['PATH'] += ':'
os.environ['PATH'] += LOCAL
print 'PATH = ' + os.environ['PATH']
Post with the original code here..
This plugin will load when you start Sublime Text 2, I personnally used it to run shell commands like I would from terminal and to fix a few plugins that werent loading due to bad path variable.
This is a super old post but I landed here looking for this solution for Sublime Text 3. Just in case people land here as well, the quick solution is to go into Preferences.sublime-settings and add:
"additional_path_items": [
"/path/to/add/1",
"/path/to/add/2",
],
Related
I would like to test (from xonsh) if a command is available or not. If I try this from the xonsh command prompt:
which bash
Then it works:
user#server ~ $ which bash
/usr/bin/bash
But it does not work from xonsh script:
#!/usr/bin/env xonsh
$RAISE_SUBPROC_ERROR = True
try:
which bash
print("bash is available")
except:
print("bash is not available")
Because it results in this error:
NameError: name 'which' is not defined
I understand that which is a shell builtin. E.g. it is not an executable file. But it is available at the xnosh command prompt. Then why it is not available inside an xonsh script? The ultimate question is this: how can I test (from an xonsh script) if a (subprocess mode) command is available or not?
import shutil
print(shutil.which('bash'))
While nagylzs' answer led me to the right solution, I found it inadequate.
shutil.which defaults to os.environ['PATH']. On my machine, the default os.environ['PATH'] doesn't contain the active PATH recognized by xonsh.
~ $ os.environ['PATH']
'/usr/bin:/bin:/usr/sbin:/sbin'
I found I needed to pass $PATH to reliably resolve 'which' in the xonsh environment.
~ $ $PATH[:2]
['/opt/google-cloud-sdk/bin', '/Users/jaraco/.local/bin']
~ $ import shutil
~ $ shutil.which('brew', path=os.pathsep.join($PATH))
'/opt/homebrew/bin/brew'
The latest version of xonsh includes a built-in which command. Unfortunately, the version included will emit an error on stdout if the target isn't found, a behavior that is not great for non-interactive use.
As mentioned in another answer, which exists in the current version of xonsh (0.13.4 as of 15/12/2022) so your script would work. However, it outputs its own error message so it's necessary to redirect stderr to get rid of it.
Also, unless you redirect its stdout as well (using all>), it migh be a good idea to capture its output so the final version would look like this:
#!/usr/bin/env xonsh
$RAISE_SUBPROC_ERROR = True
try:
bash = $(which bash err> /dev/null)
print(f"bash is available: {bash}")
except:
print("bash is not available")
When I use any command with sudo the environment variables are not there. For example after setting HTTP_PROXY the command wget works fine without sudo. However if I type sudo wget it says it can't bypass the proxy setting.
First you need to export HTTP_PROXY. Second, you need to read man sudo, and look at the -E flag. This works:
$ export HTTP_PROXY=foof
$ sudo -E bash -c 'echo $HTTP_PROXY'
Here is the quote from the man page:
-E, --preserve-env
Indicates to the security policy that the user wishes to preserve their
existing environment variables. The security policy may return an error
if the user does not have permission to preserve the environment.
The trick is to add environment variables to sudoers file via sudo visudo command and add these lines:
Defaults env_keep += "ftp_proxy http_proxy https_proxy no_proxy"
taken from ArchLinux wiki.
For Ubuntu 14, you need to specify in separate lines as it returns the errors for multi-variable lines:
Defaults env_keep += "http_proxy"
Defaults env_keep += "https_proxy"
Defaults env_keep += "HTTP_PROXY"
Defaults env_keep += "HTTPS_PROXY"
For individual variables you want to make available on a one off basis you can make it part of the command.
sudo http_proxy=$http_proxy wget "http://stackoverflow.com"
You can also combine the two env_keep statements in Ahmed Aswani's answer into a single statement like this:
Defaults env_keep += "http_proxy https_proxy"
You should also consider specifying env_keep for only a single command like this:
Defaults!/bin/[your_command] env_keep += "http_proxy https_proxy"
A simple wrapper function (or in-line for loop)
I came up with a unique solution because:
sudo -E "$#" was leaking variables that was causing problems for my command
sudo VAR1="$VAR1" ... VAR42="$VAR42" "$#" was long and ugly in my case
demo.sh
#!/bin/bash
function sudo_exports(){
eval sudo $(for x in $_EXPORTS; do printf '%q=%q ' "$x" "${!x}"; done;) "$#"
}
# create a test script to call as sudo
echo 'echo Forty-Two is $VAR42' > sudo_test.sh
chmod +x sudo_test.sh
export VAR42="The Answer to the Ultimate Question of Life, The Universe, and Everything."
export _EXPORTS="_EXPORTS VAR1 VAR2 VAR3 VAR4 VAR5 VAR6 VAR7 VAR8 VAR9 VAR10 VAR11 VAR12 VAR13 VAR14 VAR15 VAR16 VAR17 VAR18 VAR19 VAR20 VAR21 VAR22 VAR23 VAR24 VAR25 VAR26 VAR27 VAR28 VAR29 VAR30 VAR31 VAR32 VAR33 VAR34 VAR35 VAR36 VAR37 VAR38 VAR39 VAR40 VAR41 VAR42"
# clean function style
sudo_exports ./sudo_test.sh
# or just use the content of the function
eval sudo $(for x in $_EXPORTS; do printf '%q=%q ' "$x" "${!x}"; done;) ./sudo_test.sh
Result
$ ./demo.sh
Forty-Two is The Answer to the Ultimate Question of Life, The Universe, and Everything.
Forty-Two is The Answer to the Ultimate Question of Life, The Universe, and Everything.
How?
This is made possible by a feature of the bash builtin printf. The %q produces a shell quoted string. Unlike the parameter expansion in bash 4.4, this works in bash versions < 4.0
Add code snippets to /etc/sudoers.d
Don't know if this is available in all distros, but in Debian-based distros, there is a line at or near the tail of the /etc/sudoers file that includes the folder /etc/sudoers.d. Herein, one may add code "snippets" that modify sudo's configuration. Specifically, they allow control over all environment variables used in sudo.
As with /etc/sudoers, these "code snippets" should be edited using visudo. You can start by reading the README file, which is also a handy place for keeping any notes you care to make:
$ sudo visudo -f /etc/sudoers.d/README
# files for your snippets may be created/edited like so:
$ sudo visudo -f /etc/sudoers.d/20_mysnippets
Read the "Command Environment" section of 'man 5 sudoers'
Perhaps the most informative documentation on environment configuration in sudo is found in the Command environment section of man 5 sudoers. Here, we learn that a sudoers environment variables that are blocked by default may be "whitelisted" using the env_check or env_keep options; e.g.
Defaults env_keep += "http_proxy HTTP_PROXY"
Defaults env_keep += "https_proxy HTTPS_PROXY"
Defaults env_keep += "ftp_proxy FTP_PROXY"
And so, in the OP's case, we may "pass" the sudoer's environment variables as follows:
$ sudo visudo -f /etc/sudoers.d/10_myenvwlist
# opens the default editor for entry of the following lines:
Defaults env_keep += "http_proxy HTTP_PROXY"
Defaults env_keep += "https_proxy HTTPS_PROXY"
# and any others deemed useful/necessary
# Save the file, close the editor, and you are done!
Get your bearings from '# sudo -V'
The OP presumably discovered the missing environment variable in sudo by trial-and-error. However, it is possible to be proactive: A listing of all environment variables, and their allowed or denied status is available (and unique to each host) from the root prompt as follows:
# sudo -V
...
Environment variables to check for safety:
...
Environment variables to remove:
...
Environment variables to preserve:
...
Note that once an environment variable is "whitelisted" as above, it will appear in subsequent listings of sudo -V under the "preserve" listing.
If you have the need to keep the environment variables in a script you can put your command in a here document like this. Especially if you have lots of variables to set things look tidy this way.
# prepare a script e.g. for running maven
runmaven=/tmp/runmaven$$
# create the script with a here document
cat << EOF > $runmaven
#!/bin/bash
# run the maven clean with environment variables set
export ANT_HOME=/usr/share/ant
export MAKEFLAGS=-j4
mvn clean install
EOF
# make the script executable
chmod +x $runmaven
# run it
sudo $runmaven
# remove it or comment out to keep
rm $runmaven
I'm trying to determine the location of the 'flutter' script on a user's computer using this Dart code:
Process.run('which', ['flutter'], runInShell: true).then((results) {
print('which returned code ${results.exitCode}\n StdOut: ${results.stdout}\n StdErr: ${results.stderr}');
}
The problem is that the PATH environment has been set in the user's .bash_profile file like this:
export PATH=$PATH:/Users/mr_pink/dev/flutter/bin
but apparently the .bash_profile script doesn't get loaded when I call Process.run. How can I make sure it is loaded so that the "which flutter" command uses the correct PATH variable?
After reading man bash I found the solution was to add -l to the bash command like this:
Process.run('bash', ['-l', '-c', 'which flutter'])
I'm using the Sublime Text 3 with Ruby On Rails projects.
Some time ago, I setup CTags using this tutorial.
It was fine, but suddenly stopped to work. I'm getting the following error when try to rebuild the tags of project.
/bin/sh: ctags_for_ruby: command not found
These are my files:
/usr/local/bin/ctags_for_ruby:
#!/usr/bin/env ruby
system "find . -name '*.rb' | ctags -f .tags -L -"
if File.exist? './Gemfile'
require 'bundler'
paths = Bundler.load.specs.map(&:full_gem_path).join(' ')
system "ctags -R -f .gemtags #{paths}"
end
~/Library/Application Support/Sublime Text 3/Packages/User/CTags.sublime-settings
{
"debug" : false,
"autocomplete": false,
"command" : "ctags_for_ruby",
"filters" : {
"source.python": {"type":"^i$"}
},
"definition_filters": {
"source.php": {"type":"^v$"}
},
"definition_current_first": true,
"show_context_menus": true,
"extra_tag_paths" : [ [["source.python", "windows"], "C:\\Python27\\Lib\\tags"]],
"extra_tag_files" : [".gemtags", ".tags"]
}
And the $PATH variable includes /usr/local/bin directory.
Why Sublime can't find/execute the ctags_for_ruby file?
/usr/local/bin may be in your shell's $PATH, but it is not getting picked up by Sublime. To fix this, edit ~/Library/Application Support/Sublime Text 3/Packages/User/CTags.sublime-settings and change the "command" setting to "/usr/local/bin/ctags_for_ruby". Also, unless you are using the system Ruby in /usr/bin, you might want to edit the first line of /usr/local/bin/ctags_for_ruby from #/usr/bin/env ruby to the direct path of your Ruby interpreter - you can find this by running which ruby on the command line.
I've been using sbox with a Make-based codebase with no problems. Now
I'm using a scons-based codebase, and am getting some odd problems.
It seems that within scratchbox, scons can't find g++. For example, it
attempts to execute things like:
o hello hello.c
When it should be doing:
g++ -o hello hello.c
So presumably its g++ string variable is empty. g++ is present and in
the PATH - "which g++" produces /scratchbox/compilers/bin/g++.
The same source builds fine outside of scratchbox, so it shouldn't be
a problem with scons or the codebase. There are no special environment
variables set outside of scratchbox when it works.
If I symbolically link /usr/bin/g++ to /scratchbox/compilers/bin/g++,
it gets a bit further (produces the correct-looking g++ commands) but
then upon executing them produces:
sb_gcc_wrapper (g++):
/scratchbox/compilers/arm-linux-cs2007q3-51sb3/bin/sbox-arm-none-linux-gnueabi-g++:
No such file or directory
The file listed is present.
PATH contains /scratchbox/compilers/bin, SBOX_REDIRECT_FROM_DIRS contains /usr/bin and SBOX_REDIRECT_TO_DIRS contains /scratchbox/compilers/bin, so I think it should be able to find it.
Any suggestions would be appreciated!
Thanks,
Ray
Edit: Perhaps related - it also can't find pkg-config unless I prepend the full path within the scons file
scons does not propagate the PATH environment variable, so testing e.g. 'which g++' doesn't help much.
Either set the compilers directly, e.g.
env['CXX'] = '/scratchbox/compilers/bin/g++'
Build your own explicit PATH
path = ['/scratchbox/compilers/bin/','/bin', '/usr/bin', '/sbin','/usr/sbin']
env = Environment(ENV = {'PATH' : path})
Or use the PATH env variable from your shell
import os
env = Environment(ENV = {'PATH' : os.environ['PATH']})