run()/Sudo() akan dengan cerdas melihat bahwa Anda akan pergi ke localhost dan hanya menjalankan local() sebagai gantinya. Ini mungkin akan menjadi hal opsional.
Komentar dari Jeff di IRC:
dan ya, maksud saya akan selalu ada overhead dengan ssh vs pipa lurus begitu saja Saya tidak berpikir akan sangat sulit untuk memperbarui run/Sudo (terutama di master sekarang karena mereka telah di-refactored) untuk memanggil/mengembalikan local( ) secara cerdas saya tidak yakin bahwa saya ingin perilaku semi magis itu di inti (bahkan dengan itu dimatikan secara default dengan optin untuk mengaktifkannya, itu akan membantu) tetapi meskipun demikian, itu akan menjadi eksperimen yang menarik. dan jika sesederhana yang saya pikirkan, sejujurnya saya tidak dapat menemukan alasan yang baik untuk tidak melakukannya (sekali lagi asalkan itu bukan perilaku default)
Awalnya disampaikan oleh Nick Welch ( mackstann ) pada 2009/11/11 di 01:39 EST
James Pearson (xiong.chiamiov) memposting:
Seperti yang juga disebutkan di irc, saya biasanya tidak menjalankan server ssh di mesin desktop, jadi saya sebenarnya tidak bisa ssh ke localhost.
pada 2009/11/11 at 3:13 EST
Travis Swicegood ( tswicegood ) memposting:
Saya baru saja mengimplementasikan sesuatu yang serupa malam ini dalam bentuk fungsi fabric.operations baru yang disebut do
. Itu terlihat di env.run_as
untuk melihat apakah itu sama dengan "lokal", dan dengan demikian beralih ke metode local
alih-alih run
(atau sudo
jika sudo=True
dilewatkan sebagai kwarg). Ini juga menangani awalan perintah lokal dengan sudo
jika mereka menjalankan lokal.
Ini semacam cara berbeda untuk mengatasi masalah ini yang berfungsi tanpa mengubah perilaku run
atau sudo
. Perubahan ini tersedia di repositori saya .
pada 11-01-2010 pukul 12:22 EST
Morgan Goose ( goosemo ) memposting:
Saya benar-benar tidak melihat ini masuk akal. Apa gunanya menjalankan sebagai lokal. Salah satu persyaratan Fabric adalah sshd berjalan di mesin, jarak jauh atau loopback. Masalah lainnya adalah bahwa hanya mengubah lokal tidak memperhitungkan put, get, rsync_project, dan lainnya yang semuanya masih membutuhkan ssh. Mencoba mengimplementasikannya, hanya akan menyebabkan lebih banyak masalah, karena sekarang dalam ranah membuat fabfiles diterjemahkan ke bash.
pada 13-03-2011 pukul 23:14 EDT
Jeff Forcier ( bitprophet ) memposting:
Meskipun saya juga tidak 100% yakin bahwa ini adalah ide yang bagus, ini jelas merupakan sesuatu yang dibutuhkan oleh sejumlah pengguna -- permintaan lain telah diajukan sebagai #364 dengan penjelasan lain tentang kasus penggunaan.
Saya juga menambahkan tiket dry-run yang terkait dengan yang ini, karena (saya berasumsi - jika ada pengguna yang meminta dapat memverifikasi ini, itu bagus) kasus penggunaan utama untuk fitur ini adalah untuk pengujian/pengeringan- berlari.
pada 23-06-2011 pukul 11:26 EDT
Seperti disebutkan di #538, jika kita dapat sepenuhnya menormalkan ketiga runner sehingga dapat digunakan secara bergantian, kita harus memastikan bahwa pelepasan shell bekerja secara konsisten di ketiga runner tersebut. Saat ini kami tidak shell escape local
, meskipun itu setidaknya sebagian karena tidak menggunakan pembungkus shell.
Jika ada yang bertanya-tanya "mengapa ada orang yang melakukan ini?", Jawabannya adalah jika Anda memiliki pipa penyebaran, akan sangat membantu untuk menjalankan skrip penyebaran yang sama persis, tidak peduli lingkungan mana, daripada memiliki skrip pengaturan khusus untuk localhost vs segala sesuatu yang lain.
+1 untuk fitur
+1
+10
+1
+1
Untuk menahan Anda, Anda bisa memastikan Anda menjalankan server OpenSSH. Pertama-tama lakukan sudo apt-get install ssh
untuk memastikan Anda telah menginstalnya (bahkan jika Anda merasa sudah menginstalnya). Kemudian lakukan sudo service ssh start
| stop
| restart
sesuai kebutuhan. Belajar dari thread ini .
+1
Kasus penggunaan saya sederhana: Saya ingin menggunakan skrip django-deploy yang sama untuk mengonfigurasi instans ec2 baik dengan cloud-init melalui CloudWatch (kasus untuk menjalankan perintah lokal) dan menggunakan fab deploy_django -H foo@bar
.
+1
Ini akan sangat berguna. Satu kasus penggunaan yang saya miliki adalah menggunakan penyedia shell gelandangan untuk mengonfigurasi vm tertentu menggunakan fabric dan tanpa perlu ssh localhost.
+1
Saya terkejut tidak melihat ini di Fabric.
FYI: Implementasi fitur ini menjadi lebih kompleks ketika Anda memikirkan fungsi fabric seperti reboot()
.
+1
Seharusnya sudah menjadi bagian dari inti !
+1
Sangat masuk akal: dari sudut pandang abstrak, local
hanyalah kasus khusus dari run
, di mana tidak ada mesin SSH yang terlibat.
Satu hal lagi untuk ditunjukkan (mungkin jelas): Fabric harus cukup pintar untuk memutuskan apakah run
harus dikonversi ke local
SETELAH membaca /etc/hosts.
Maksud saya: jika kita punya
env.host = [ 'mywebserver' ]
dan di /etc/hosts kita memiliki:
127.0.0.1 mywebserver
maka, setiap panggilan run
sebenarnya adalah panggilan local
.
Mengambil konsep ini selangkah lebih maju, kita juga harus memperlakukan run
sebagai panggilan lokal ketika host jarak jauh memutuskan ke IP yang ditetapkan ke antarmuka jaringan mesin lokal.
Misalnya:
file bagus:
env.host = [ 'mywebserver' ]
/etc/hosts:
192.168.1.1 mywebserver
ip addr
:
[...]
eth0:
inet 192.168.1.1
[...]
+1
+1 :+1:
:+1:
+1
+1
Fabric 2 akan menggunakan pyinvoke/invoke jadi ini seharusnya cukup mudah dilakukan di sana. Saya akan menunggu Fabric 2 untuk cara non-retas untuk melakukan ini.
:+1:
+1
:+1:
:+1: Harap terapkan ini, terutama karena komputer mac tidak secara otomatis diatur untuk memiliki terowongan SSH yang dikonfigurasi untuk akses jarak jauh ke server localhost.
+1
+1 :)
+1 tolong
:+1:
:+1:
:+1:
Kami menggunakan Fab untuk membangun paket debian dan ini menambah kerumitan ekstra
teman-teman, halo semua
saya mencoba membuat tiruan kain dengan perbedaan:
Anda dapat melihat jika Anda membutuhkan fitur ini
https://github.com/Friz-zy/factory
Saya mungkin melewatkan sesuatu dalam diskusi ini, tetapi inilah yang saya lakukan untuk menggunakan kode yang sama dengan perintah fab run
pada mesin localhost dan remote.
env.use_ssh_config = True
di fabfile.py sayaIni tidak menyelesaikan masalah Anda jika Anda tidak menjalankan server ssh di mesin lokal Anda
:+1:
+1
+1 Harap terapkan fitur ini :)
+1
Bisa sangat berguna untuk mem-bootstrap gambar Docker menggunakan skrip Fabric yang ada. Fitur ini akan menghindari untuk menginstal server SSH pada wadah, yang bertentangan dengan praktik terbaik Docker
+1
+1
+1
Selanjutnya untuk jawaban yang diberikan oleh @AntoniosHadji , berikut adalah instruksi lengkap untuk membuatnya berfungsi;
# Generate new SSH key for local usage
ssh-keygen -f ~/.ssh/id_rsa -N ''
# Add server keys to users known hosts (eliminates 'are you sure' messages);
ssh-keyscan -H localhost > ~/.ssh/known_hosts
# Allow user to ssh to itself
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
Sebenarnya, ini bisa dilakukan dengan menggunakan masakan . Anda perlu mengubah semua run
eksekusi untuk referensi fungsi cuisine.run
, yang dapat dilakukan dengan mudah dengan impor, dan mengubah mode ke lokal:
from cuisine import run, mode_local
mode_local()
print run("echo Hello")
Hebat @cgarciaarano
Untuk kasus penggunaan sederhana, ini berfungsi untuk saya:
from fabric.api import run, local
# ...
# in task:
if env.host is None or env.host == 'localhost':
run = local
:+1:
Saya ingin fabfile saya berjalan dari jarak jauh atau lokal ketika ssh bukan pilihan. Ini termasuk pembungkus lokal untuk get/put/exists dll.
:+1: Saya memiliki fabfiles yang berjalan baik secara lokal maupun jarak jauh dan saya akhirnya meretas fungsi pembungkus saya sendiri untuk menjalankan/lokal/menangani semua perbedaan halus seperti pengambilan keluaran dan penanganan kesalahan.
Bagaimana jika Anda memiliki koneksi ssh yang melakukan penerusan port dinamis dan pengikatan pada 127.0.0.2 (masih secara teknis localhost) pada port 2223. Saya dapat melihat bagaimana ini dapat menyebabkan masalah, untuk itu mencocokkan pada localhost dan menyelesaikan ke 127.0.0.1 daripada juga mendukung seluruh kelas 127.0.0.0/8 mungkin merupakan ide yang baik untuk ditangani.
@blade2005 Ya, seluruh rentang 127._._.* menunjuk ke localhost Anda (kecuali 127.0.0.0 dan 127.255.255.255) tetapi ketika Anda benar-benar menunjuk ke localhost Anda, Anda tidak akan menggunakan port kan?
Jadi saya percaya bahwa kita dapat dengan aman berasumsi bahwa 127.*.*.* == localhost
dan ssh dapat dihindari tetapi 127.*.*.*:*
menunjuk ke port yang diteruskan dan ssh diperlukan.
Sejujurnya, fitur ini mungkin lebih masuk akal sebagai plugin pihak ke-3 yang dibangun di atas kain, mirip dengan perpustakaan masakan. Kemudian kami hanya akan mengimpor fungsi yang dibungkus untuk run/get/put/etc, yang akan mengetahui apakah akan dijalankan secara lokal atau jarak jauh berdasarkan variabel env. Setidaknya dengan cara ini, seseorang dapat memulai ini untuk digunakan semua orang.
Saya mengimplementasikan sesuatu secara lokal, dan ini lebih banyak berfungsi daripada hanya beralih antara lokal/jalankan. Anda harus mempertimbangkan awalan, direktori yang diubah, pengguna sudo, dll.
Secara singkat memikirkan hal ini dalam konteks tiket terkait 2.0 lainnya, dan menyadari bahwa ada lebih banyak lagi yang muncul selain hanya " run
menjadi rebinding dari local
":
local
dan run
, atau salah satu dari put
/ get
, secara inheren menjadi bermasalah: operasi dengan definisi yang jelas 'lokal' dan 'jarak jauh' "berakhir" sekarang keduanya menunjuk secara lokal.run
atau sudo
menaikkan DoesntMakeAnySenseError
" atau apa pun.put
/ get
mungkin bisa berubah menjadi shutil.copy
atau sejenisnyalocal
mungkin tidak akan diubah (walaupun saat mencetak apa yang terjadi, mungkin masih ingin dibedakan dari apa yang diawali dengan run-except-locally
...?)prefix
, cd
dll semuanya perlu dijawab pertanyaan serupa.sudo
secara lokal, berpotensi besar dan mungkin memerlukan pemeriksaan keamanan tambahan.local
, yang merupakan kemungkinan lain. Meskipun bukan perintah yang besar, perintah sudo
yang bahkan bekerja secara lokal (yaitu yang di-deploy ke, dan di-deploy dari, Linux) mungkin perlu tetap diistimewakan secara lokal (mis. apt
/ yum
dan teman-teman, mengutak-atik firewall, dll).sudo
juga (seperti yang disebutkan di atas oleh Jon) perlu meningkatkan kemungkinan untuk mengonfigurasi vektor konfigurasi lokal-vs-jarak jauh yang berbeda karena pengguna Sudo, kata sandi, dll cenderung berbeda antara kedua sisi.localhost
hanya akan diberikan nilai yang sesuai. (Plus, sebagai subkelas "untuk menjalankan hal-hal jarak jauh secara lokal" khusus, Context
ia dapat melakukan hal-hal lain juga, jika diperlukan).@max-arnold sedang mencoba ini di v2 alpha dan mengalami masalah yang membingungkan, yang diharapkan pada saat ini karena - saya belum sampai ke kasus penggunaan tiket khusus ini, selain memastikan run
dan local
memiliki API yang serupa mungkin.
Saat ini, masalah besar hanyalah sifat dan API objek yang terikat pada konteks tugas ( c
atau ctx
atau apa pun namanya) posarg. Saat ini, dan sekali lagi, ini tidak dimaksudkan untuk menjadi final, hanya bagaimana akhirnya sejauh ini:
Executor
, atau oleh Fab 2 FabExecutor
ketika tidak ada host yang hadir, itu adalah invoke.Context
, yang memiliki run
yang berjalan secara lokal , dan tidak memiliki local
;fabric.Connection
, yang run
berjalan dari jarak jauh, dan yang local
adalah rebinding dari run
Invoke Diperlukan pemikiran yang lebih spesifik, termasuk melihat kasus penggunaan di sini dan di tiket terkait. Brainstorming begitu saja:
patchwork
(née contrib
) dan/atau invocations
(Memanggil versi yang sama), terutama karena ini menginformasikan seberapa banyak mereka dapat berbagi kode melakukan. Banyak tugas dan/atau subrutin dalam basis kode semacam itu mungkin ingin dijalankan secara lokal atau jarak jauh.@task
dan/atau kwargs sama, di mana pengguna dapat menyatakan harapan mereka (yaitu "Saya benar-benar ingin diberikan konteks yang mampu jarak jauh", "tolong jangan pernah memberi saya konteks yang mampu jarak jauh", dll)@task
/ Task
; basis kode pure-Invoke hanya akan menggunakan @task
yang akan selalu memicu diberi vanilla Context
, sementara tugas yang dibuat melalui versi Fabric setidaknya memiliki opsi untuk diberikan Connection
, jika tidak memerlukannya.ctx.run()
ada_.@task
, dengan pemahaman bahwa seseorang dari sudut pandang pemanggilan Fabric (atau seperti Fabric) memiliki opsi untuk memberikannya tugaskan Connection
alih-alih Context
.local
ketika tidak ada (Kode yang mengharapkan Kain/Sambungan dijalankan melalui Invoke)run
untuk berjalan secara lokal ketika seseorang malah diberi konteks dengan remote run
(Panggilan/kode yang mengharapkan konteks dijalankan melalui Fabric)Connection('localhost').run('foo')
untuk _tidak menggunakan SSH_ tetapi bertindak persis seperti Connection('localhost').local('foo')
.ssh.localhost_becomes_subprocess = True
atau apa pun.)Satu-satunya usecase saya di sini saat ini adalah upload_template()
dapat merender template secara lokal.
Tentu saja orang bisa melakukannya seperti ini:
#http://matthiaseisen.com/pp/patterns/p0198/
import os
import jinja2
def render(tpl_path, context):
path, filename = os.path.split(tpl_path)
return jinja2.Environment(
loader=jinja2.FileSystemLoader(path or './')
).get_template(filename).render(context)
Tetapi mengapa tidak memiliki opsi untuk merender secara lokal?
Penggunaan utama fitur ini, dalam kasus saya, adalah untuk menyebarkan konfigurasi aplikasi ke mesin lokal saya untuk pengujian lokal.
Pertimbangkan Anda memiliki settings.py.j2
yang dirender ke server tujuan setelah penerapan dan di sana bernama settings.py
dan hanya berisi kode python, tanpa jinja.
Sekarang Anda ingin menguji secara lokal, tetapi secara lokal belum ada settings.py
, karena perlu dirender dari settings.py.j2
.
Jadi aplikasi Anda tidak dapat memulai, dan Anda harus membuat settings.py
secara manual untuk pengujian lokal Anda.
Ini sangat melelahkan, dan seharusnya lebih mudah.
Misalnya, di Ansible saya hanya akan memberi tahu tugas bahwa itu akan menggunakan "koneksi lokal", dan itu akan dirender pada Host lokal tanpa mencoba ssh ke dalamnya.
Sampai fitur ini tersedia di Fabric, saya akan menggunakan solusi yang ditempelkan di atas, tentu saja, karena ini hanya beberapa baris kode. Seharusnya lebih mudah meskipun imho. Saya merasa itu benar-benar jenis kain yang seharusnya memudahkan saya.
@fninja Saya belum mem-porting upload_template
itu sendiri tapi saya sangat setuju bahwa itu termasuk dalam ruang masalah ini. Bisa dibilang orang bisa menangani ini hanya dengan memisahkan langkah render pembungkus Jinja dan langkah upload-beberapa-string upload, terutama karena yang terakhir sudah ada dalam bentuk "serahkan FLO ke put
". Misalnya:
from StringIO import StringIO # too lazy to remember the newer path offhand
from somewhere.jinja_wrapper import render
from invoke import task
<strong i="9">@task</strong>
def render_settings(c):
rendered = render('settings.py.j2', {'template': 'params'})
c.put(StringIO(rendered), 'remote/path/to/settings.py')
Tapi mungkin masih ada ruang untuk analog 1-stop yang lebih pendek lagi ke upload_template
yang bisa berupa metode Connection
atau subrutin yang mengambil argumen Connection
.
Either way, itu menimbulkan lebih banyak pertanyaan tentang: bagaimana tepatnya memperlakukan hal semacam ini - misalnya, objek Context
Invoke-only tidak memiliki put
/ get
. Apakah layak menambahkannya? Sangat masuk akal bagi pengguna Fabric dalam konteks tiket ini (maka upload_template
atau w/e cukup memanggil put
dalam kedua kasus), tetapi untuk pengguna murni-Invoke, ini aneh dan bagian API yang tidak berguna.
+1 untuk menjadikan ini fitur inti
Pos silang dari #1637. Hanya sebuah ide:
from fabric import task, local
<strong i="6">@task</strong>
<strong i="7">@local</strong>
def build(ctx):
with ctx.cd('/project/dir'):
ctx.run('build > artifact.zip')
<strong i="8">@task</strong>
def deploy(conn):
build(local(conn))
with conn.cd('/remote/path'), local(conn).cd('/project/dir'):
conn.put(remote_path='build.zip', local_path='artifact.zip')
Pada dasarnya local()
dapat bertindak sebagai dekorator/pengelola konteks/fungsi dan mengubah Connection
menjadi Context
.
Kasus penggunaan lain yang menurut saya tidak disebutkan: Membangun perpustakaan fungsi yang dapat digunakan kembali. Dalam kasus saya, sebagian besar perintah git
. Saya menulis dorun
yang terlalu sederhana yang menyembunyikan perbedaan antara parameter fungsi run
dan local
(pada v1); fungsi mana yang dipilih dilewatkan sebagai parameter. Berikut adalah git checkout
misalnya:
def git_checkout(branch, remote='origin', run=run):
"""Checkout a branch if necessary."""
if branch == git_current_branch(run=run):
return
elif branch in git_local_branches(run=run):
dorun('git checkout ' + branch, run=run)
else:
dorun('git checkout -t -b {0} {1}/{0}'.format(branch, remote), run=run)
def git_current_branch(run=run):
"""Get the current branch (aka HEAD)"""
output = dorun('git name-rev --name-only HEAD', run=run)
return output.strip()
def git_local_branches(run=run):
"""Get a list of local branches; assumes in repo directory."""
output = dorun('git branch --no-color', run=run)
branches = {l.strip().split(' ')[-1]
for l in output.strip().split('\n')}
return branches
Ini terlihat seperti ini:
from fabric.api import run as run_remote, local as run_local
def dorun(*args, **kwargs):
"""Work around the fact that "local" and "run" are very different."""
kwargs.setdefault('run', run_remote)
run = kwargs.pop('run')
if run == run_local:
kwargs.setdefault('capture', True)
elif 'capture' in kwargs:
del kwargs['capture']
return run(*args, **kwargs)
Saya tidak tahu apa yang terjadi dengan sudo
dan ada masalah yang tidak dapat saya tangani dengan mudah, seperti memperluas ~remoteuser
untuk menghasilkan jalur.
Komentar yang paling membantu
Jika ada yang bertanya-tanya "mengapa ada orang yang melakukan ini?", Jawabannya adalah jika Anda memiliki pipa penyebaran, akan sangat membantu untuk menjalankan skrip penyebaran yang sama persis, tidak peduli lingkungan mana, daripada memiliki skrip pengaturan khusus untuk localhost vs segala sesuatu yang lain.